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

Go to the source code of this file.

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 GetOldestNonRemovableTransactionId (Relation rel)
 
TransactionId GetOldestTransactionIdConsideredRunning (void)
 
TransactionId GetOldestActiveTransactionId (void)
 
TransactionId GetOldestSafeDecodingTransactionId (bool catalogOnly)
 
void GetReplicationHorizons (TransactionId *slot_xmin, TransactionId *catalog_xmin)
 
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)
 
pid_t SignalVirtualTransaction (VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
 
bool MinimumActiveBackends (int min)
 
int CountDBBackends (Oid databaseid)
 
int CountDBConnections (Oid databaseid)
 
void CancelDBBackends (Oid databaseid, ProcSignalReason sigmode, bool conflictPending)
 
int CountUserBackends (Oid roleid)
 
bool CountOtherDBBackends (Oid databaseId, int *nbackends, int *nprepared)
 
void TerminateOtherDBBackends (Oid databaseId)
 
void XidCacheRemoveRunningXids (TransactionId xid, int nxids, const TransactionId *xids, TransactionId latestXid)
 
void ProcArraySetReplicationSlotXmin (TransactionId xmin, TransactionId catalog_xmin, bool already_locked)
 
void ProcArrayGetReplicationSlotXmin (TransactionId *xmin, TransactionId *catalog_xmin)
 

Function Documentation

◆ BackendPidGetProc()

PGPROC* BackendPidGetProc ( int  pid)

Definition at line 3036 of file procarray.c.

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

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

3037 {
3038  PGPROC *result;
3039 
3040  if (pid == 0) /* never match dummy PGPROCs */
3041  return NULL;
3042 
3043  LWLockAcquire(ProcArrayLock, LW_SHARED);
3044 
3045  result = BackendPidGetProcWithLock(pid);
3046 
3047  LWLockRelease(ProcArrayLock);
3048 
3049  return result;
3050 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
PGPROC * BackendPidGetProcWithLock(int pid)
Definition: procarray.c:3059
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121

◆ BackendPidGetProcWithLock()

PGPROC* BackendPidGetProcWithLock ( int  pid)

Definition at line 3059 of file procarray.c.

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

Referenced by BackendPidGetProc(), and GetBlockerStatusData().

3060 {
3061  PGPROC *result = NULL;
3062  ProcArrayStruct *arrayP = procArray;
3063  int index;
3064 
3065  if (pid == 0) /* never match dummy PGPROCs */
3066  return NULL;
3067 
3068  for (index = 0; index < arrayP->numProcs; index++)
3069  {
3070  PGPROC *proc = &allProcs[arrayP->pgprocnos[index]];
3071 
3072  if (proc->pid == pid)
3073  {
3074  result = proc;
3075  break;
3076  }
3077  }
3078 
3079  return result;
3080 }
Definition: type.h:89
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ BackendXidGetPid()

int BackendXidGetPid ( TransactionId  xid)

Definition at line 3096 of file procarray.c.

References InvalidTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PGPROC::pid, procArray, ProcGlobal, and PROC_HDR::xids.

Referenced by pgrowlocks().

3097 {
3098  int result = 0;
3099  ProcArrayStruct *arrayP = procArray;
3100  TransactionId *other_xids = ProcGlobal->xids;
3101  int index;
3102 
3103  if (xid == InvalidTransactionId) /* never match invalid xid */
3104  return 0;
3105 
3106  LWLockAcquire(ProcArrayLock, LW_SHARED);
3107 
3108  for (index = 0; index < arrayP->numProcs; index++)
3109  {
3110  int pgprocno = arrayP->pgprocnos[index];
3111  PGPROC *proc = &allProcs[pgprocno];
3112 
3113  if (other_xids[index] == xid)
3114  {
3115  result = proc->pid;
3116  break;
3117  }
3118  }
3119 
3120  LWLockRelease(ProcArrayLock);
3121 
3122  return result;
3123 }
uint32 TransactionId
Definition: c.h:575
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CancelDBBackends()

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

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

3496 {
3497  ProcArrayStruct *arrayP = procArray;
3498  int index;
3499 
3500  /* tell all backends to die */
3501  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3502 
3503  for (index = 0; index < arrayP->numProcs; index++)
3504  {
3505  int pgprocno = arrayP->pgprocnos[index];
3506  PGPROC *proc = &allProcs[pgprocno];
3507 
3508  if (databaseid == InvalidOid || proc->databaseId == databaseid)
3509  {
3510  VirtualTransactionId procvxid;
3511  pid_t pid;
3512 
3513  GET_VXID_FROM_PGPROC(procvxid, *proc);
3514 
3515  proc->recoveryConflictPending = conflictPending;
3516  pid = proc->pid;
3517  if (pid != 0)
3518  {
3519  /*
3520  * Kill the pid if it's still here. If not, that's what we
3521  * wanted so ignore any errors.
3522  */
3523  (void) SendProcSignal(pid, sigmode, procvxid.backendId);
3524  }
3525  }
3526  }
3527 
3528  LWLockRelease(ProcArrayLock);
3529 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:256
bool recoveryConflictPending
Definition: proc.h:167
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define InvalidOid
Definition: postgres_ext.h:36
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CancelVirtualTransaction()

pid_t CancelVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode 
)

Definition at line 3326 of file procarray.c.

References SignalVirtualTransaction().

Referenced by ResolveRecoveryConflictWithVirtualXIDs().

3327 {
3328  return SignalVirtualTransaction(vxid, sigmode, true);
3329 }
pid_t SignalVirtualTransaction(VirtualTransactionId vxid, ProcSignalReason sigmode, bool conflictPending)
Definition: procarray.c:3332

◆ CountDBBackends()

int CountDBBackends ( Oid  databaseid)

Definition at line 3434 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithDatabase().

3435 {
3436  ProcArrayStruct *arrayP = procArray;
3437  int count = 0;
3438  int index;
3439 
3440  LWLockAcquire(ProcArrayLock, LW_SHARED);
3441 
3442  for (index = 0; index < arrayP->numProcs; index++)
3443  {
3444  int pgprocno = arrayP->pgprocnos[index];
3445  PGPROC *proc = &allProcs[pgprocno];
3446 
3447  if (proc->pid == 0)
3448  continue; /* do not count prepared xacts */
3449  if (!OidIsValid(databaseid) ||
3450  proc->databaseId == databaseid)
3451  count++;
3452  }
3453 
3454  LWLockRelease(ProcArrayLock);
3455 
3456  return count;
3457 }
#define OidIsValid(objectId)
Definition: c.h:698
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CountDBConnections()

int CountDBConnections ( Oid  databaseid)

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

3465 {
3466  ProcArrayStruct *arrayP = procArray;
3467  int count = 0;
3468  int index;
3469 
3470  LWLockAcquire(ProcArrayLock, LW_SHARED);
3471 
3472  for (index = 0; index < arrayP->numProcs; index++)
3473  {
3474  int pgprocno = arrayP->pgprocnos[index];
3475  PGPROC *proc = &allProcs[pgprocno];
3476 
3477  if (proc->pid == 0)
3478  continue; /* do not count prepared xacts */
3479  if (proc->isBackgroundWorker)
3480  continue; /* do not count background workers */
3481  if (!OidIsValid(databaseid) ||
3482  proc->databaseId == databaseid)
3483  count++;
3484  }
3485 
3486  LWLockRelease(ProcArrayLock);
3487 
3488  return count;
3489 }
#define OidIsValid(objectId)
Definition: c.h:698
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool isBackgroundWorker
Definition: proc.h:160
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CountOtherDBBackends()

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

Definition at line 3585 of file procarray.c.

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

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

3586 {
3587  ProcArrayStruct *arrayP = procArray;
3588 
3589 #define MAXAUTOVACPIDS 10 /* max autovacs to SIGTERM per iteration */
3590  int autovac_pids[MAXAUTOVACPIDS];
3591  int tries;
3592 
3593  /* 50 tries with 100ms sleep between tries makes 5 sec total wait */
3594  for (tries = 0; tries < 50; tries++)
3595  {
3596  int nautovacs = 0;
3597  bool found = false;
3598  int index;
3599 
3601 
3602  *nbackends = *nprepared = 0;
3603 
3604  LWLockAcquire(ProcArrayLock, LW_SHARED);
3605 
3606  for (index = 0; index < arrayP->numProcs; index++)
3607  {
3608  int pgprocno = arrayP->pgprocnos[index];
3609  PGPROC *proc = &allProcs[pgprocno];
3610  uint8 statusFlags = ProcGlobal->statusFlags[index];
3611 
3612  if (proc->databaseId != databaseId)
3613  continue;
3614  if (proc == MyProc)
3615  continue;
3616 
3617  found = true;
3618 
3619  if (proc->pid == 0)
3620  (*nprepared)++;
3621  else
3622  {
3623  (*nbackends)++;
3624  if ((statusFlags & PROC_IS_AUTOVACUUM) &&
3625  nautovacs < MAXAUTOVACPIDS)
3626  autovac_pids[nautovacs++] = proc->pid;
3627  }
3628  }
3629 
3630  LWLockRelease(ProcArrayLock);
3631 
3632  if (!found)
3633  return false; /* no conflicting backends, so done */
3634 
3635  /*
3636  * Send SIGTERM to any conflicting autovacuums before sleeping. We
3637  * postpone this step until after the loop because we don't want to
3638  * hold ProcArrayLock while issuing kill(). We have no idea what might
3639  * block kill() inside the kernel...
3640  */
3641  for (index = 0; index < nautovacs; index++)
3642  (void) kill(autovac_pids[index], SIGTERM); /* ignore any error */
3643 
3644  /* sleep, then try again */
3645  pg_usleep(100 * 1000L); /* 100ms */
3646  }
3647 
3648  return true; /* timed out, still conflicts */
3649 }
PGPROC * MyProc
Definition: proc.c:68
unsigned char uint8
Definition: c.h:427
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define kill(pid, sig)
Definition: win32_port.h:454
#define MAXAUTOVACPIDS
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
void pg_usleep(long microsec)
Definition: signal.c:53
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:100
uint8 * statusFlags
Definition: proc.h:331
Definition: proc.h:121
int pid
Definition: proc.h:146
#define PROC_IS_AUTOVACUUM
Definition: proc.h:54

◆ CountUserBackends()

int CountUserBackends ( Oid  roleid)

Definition at line 3535 of file procarray.c.

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

Referenced by InitializeSessionUserId().

3536 {
3537  ProcArrayStruct *arrayP = procArray;
3538  int count = 0;
3539  int index;
3540 
3541  LWLockAcquire(ProcArrayLock, LW_SHARED);
3542 
3543  for (index = 0; index < arrayP->numProcs; index++)
3544  {
3545  int pgprocno = arrayP->pgprocnos[index];
3546  PGPROC *proc = &allProcs[pgprocno];
3547 
3548  if (proc->pid == 0)
3549  continue; /* do not count prepared xacts */
3550  if (proc->isBackgroundWorker)
3551  continue; /* do not count background workers */
3552  if (proc->roleId == roleid)
3553  count++;
3554  }
3555 
3556  LWLockRelease(ProcArrayLock);
3557 
3558  return count;
3559 }
Oid roleId
Definition: proc.h:155
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool isBackgroundWorker
Definition: proc.h:160
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ CreateSharedProcArray()

void CreateSharedProcArray ( void  )

Definition at line 394 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

395 {
396  bool found;
397 
398  /* Create or attach to the ProcArray shared structure */
400  ShmemInitStruct("Proc Array",
401  add_size(offsetof(ProcArrayStruct, pgprocnos),
402  mul_size(sizeof(int),
404  &found);
405 
406  if (!found)
407  {
408  /*
409  * We're the first - initialize.
410  */
411  procArray->numProcs = 0;
422  }
423 
425 
426  /* Create or attach to the KnownAssignedXids arrays too, if needed */
427  if (EnableHotStandby)
428  {
430  ShmemInitStruct("KnownAssignedXids",
431  mul_size(sizeof(TransactionId),
433  &found);
434  KnownAssignedXidsValid = (bool *)
435  ShmemInitStruct("KnownAssignedXidsValid",
436  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS),
437  &found);
438  }
439 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:575
#define SpinLockInit(lock)
Definition: spin.h:60
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
uint64 xactCompletionCount
Definition: transam.h:241
slock_t known_assigned_xids_lck
Definition: procarray.c:84
PROC_HDR * ProcGlobal
Definition: proc.c:80
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
VariableCache ShmemVariableCache
Definition: varsup.c:34
int maxKnownAssignedXids
Definition: procarray.c:80
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:252
int numKnownAssignedXids
Definition: procarray.c:81
static bool * KnownAssignedXidsValid
Definition: procarray.c:258
TransactionId lastOverflowedXid
Definition: procarray.c:93
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define TOTAL_MAX_CACHED_SUBXIDS
static TransactionId * KnownAssignedXids
Definition: procarray.c:257
bool EnableHotStandby
Definition: xlog.c:98
PGPROC * allProcs
Definition: proc.h:316
int tailKnownAssignedXids
Definition: procarray.c:82
#define offsetof(type, field)
Definition: c.h:715
int headKnownAssignedXids
Definition: procarray.c:83

◆ ExpireAllKnownAssignedTransactionIds()

void ExpireAllKnownAssignedTransactionIds ( void  )

Definition at line 4363 of file procarray.c.

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

Referenced by ShutdownRecoveryTransactionEnvironment().

4364 {
4365  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4367  LWLockRelease(ProcArrayLock);
4368 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4812
#define InvalidTransactionId
Definition: transam.h:31
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206

◆ ExpireOldKnownAssignedTransactionIds()

void ExpireOldKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4375 of file procarray.c.

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

Referenced by ProcArrayApplyRecoveryInfo().

4376 {
4377  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4379  LWLockRelease(ProcArrayLock);
4380 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
static void KnownAssignedXidsRemovePreceding(TransactionId xid)
Definition: procarray.c:4812
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206

◆ ExpireTreeKnownAssignedTransactionIds()

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

Definition at line 4337 of file procarray.c.

References Assert, KnownAssignedXidsRemoveTree(), LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXidRecovery(), ShmemVariableCache, STANDBY_INITIALIZED, standbyState, and VariableCacheData::xactCompletionCount.

Referenced by xact_redo_abort(), and xact_redo_commit().

4339 {
4341 
4342  /*
4343  * Uses same locking as transaction commit
4344  */
4345  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
4346 
4347  KnownAssignedXidsRemoveTree(xid, nsubxids, subxids);
4348 
4349  /* As in ProcArrayEndTransaction, advance latestCompletedXid */
4351 
4352  /* ... and xactCompletionCount */
4354 
4355  LWLockRelease(ProcArrayLock);
4356 }
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:935
uint64 xactCompletionCount
Definition: transam.h:241
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
VariableCache ShmemVariableCache
Definition: varsup.c:34
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4790
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
HotStandbyState standbyState
Definition: xlog.c:209

◆ GetConflictingVirtualXIDs()

VirtualTransactionId* GetConflictingVirtualXIDs ( TransactionId  limitXmin,
Oid  dbOid 
)

Definition at line 3252 of file procarray.c.

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

Referenced by ResolveRecoveryConflictWithSnapshot(), and ResolveRecoveryConflictWithTablespace().

3253 {
3254  static VirtualTransactionId *vxids;
3255  ProcArrayStruct *arrayP = procArray;
3256  int count = 0;
3257  int index;
3258 
3259  /*
3260  * If first time through, get workspace to remember main XIDs in. We
3261  * malloc it permanently to avoid repeated palloc/pfree overhead. Allow
3262  * result space, remembering room for a terminator.
3263  */
3264  if (vxids == NULL)
3265  {
3266  vxids = (VirtualTransactionId *)
3267  malloc(sizeof(VirtualTransactionId) * (arrayP->maxProcs + 1));
3268  if (vxids == NULL)
3269  ereport(ERROR,
3270  (errcode(ERRCODE_OUT_OF_MEMORY),
3271  errmsg("out of memory")));
3272  }
3273 
3274  LWLockAcquire(ProcArrayLock, LW_SHARED);
3275 
3276  for (index = 0; index < arrayP->numProcs; index++)
3277  {
3278  int pgprocno = arrayP->pgprocnos[index];
3279  PGPROC *proc = &allProcs[pgprocno];
3280 
3281  /* Exclude prepared transactions */
3282  if (proc->pid == 0)
3283  continue;
3284 
3285  if (!OidIsValid(dbOid) ||
3286  proc->databaseId == dbOid)
3287  {
3288  /* Fetch xmin just once - can't change on us, but good coding */
3289  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3290 
3291  /*
3292  * We ignore an invalid pxmin because this means that backend has
3293  * no snapshot currently. We hold a Share lock to avoid contention
3294  * with users taking snapshots. That is not a problem because the
3295  * current xmin is always at least one higher than the latest
3296  * removed xid, so any new snapshot would never conflict with the
3297  * test here.
3298  */
3299  if (!TransactionIdIsValid(limitXmin) ||
3300  (TransactionIdIsValid(pxmin) && !TransactionIdFollows(pxmin, limitXmin)))
3301  {
3302  VirtualTransactionId vxid;
3303 
3304  GET_VXID_FROM_PGPROC(vxid, *proc);
3305  if (VirtualTransactionIdIsValid(vxid))
3306  vxids[count++] = vxid;
3307  }
3308  }
3309  }
3310 
3311  LWLockRelease(ProcArrayLock);
3312 
3313  /* add the terminator */
3314  vxids[count].backendId = InvalidBackendId;
3316 
3317  return vxids;
3318 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:575
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:704
LocalTransactionId localTransactionId
Definition: lock.h:65
#define OidIsValid(objectId)
Definition: c.h:698
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define ERROR
Definition: elog.h:45
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
#define InvalidBackendId
Definition: backendid.h:23
#define ereport(elevel,...)
Definition: elog.h:155
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define InvalidLocalTransactionId
Definition: lock.h:68
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ GetCurrentVirtualXIDs()

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

Definition at line 3164 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, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsValid, TransactionIdPrecedesOrEquals(), UINT32_ACCESS_ONCE, VirtualTransactionIdIsValid, and PGPROC::xmin.

Referenced by WaitForOlderSnapshots().

3167 {
3168  VirtualTransactionId *vxids;
3169  ProcArrayStruct *arrayP = procArray;
3170  int count = 0;
3171  int index;
3172 
3173  /* allocate what's certainly enough result space */
3174  vxids = (VirtualTransactionId *)
3175  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
3176 
3177  LWLockAcquire(ProcArrayLock, LW_SHARED);
3178 
3179  for (index = 0; index < arrayP->numProcs; index++)
3180  {
3181  int pgprocno = arrayP->pgprocnos[index];
3182  PGPROC *proc = &allProcs[pgprocno];
3183  uint8 statusFlags = ProcGlobal->statusFlags[index];
3184 
3185  if (proc == MyProc)
3186  continue;
3187 
3188  if (excludeVacuum & statusFlags)
3189  continue;
3190 
3191  if (allDbs || proc->databaseId == MyDatabaseId)
3192  {
3193  /* Fetch xmin just once - might change on us */
3194  TransactionId pxmin = UINT32_ACCESS_ONCE(proc->xmin);
3195 
3196  if (excludeXmin0 && !TransactionIdIsValid(pxmin))
3197  continue;
3198 
3199  /*
3200  * InvalidTransactionId precedes all other XIDs, so a proc that
3201  * hasn't set xmin yet will not be rejected by this test.
3202  */
3203  if (!TransactionIdIsValid(limitXmin) ||
3204  TransactionIdPrecedesOrEquals(pxmin, limitXmin))
3205  {
3206  VirtualTransactionId vxid;
3207 
3208  GET_VXID_FROM_PGPROC(vxid, *proc);
3209  if (VirtualTransactionIdIsValid(vxid))
3210  vxids[count++] = vxid;
3211  }
3212  }
3213  }
3214 
3215  LWLockRelease(ProcArrayLock);
3216 
3217  *nvxids = count;
3218  return vxids;
3219 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
uint32 TransactionId
Definition: c.h:575
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
unsigned char uint8
Definition: c.h:427
PROC_HDR * ProcGlobal
Definition: proc.c:80
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
Oid MyDatabaseId
Definition: globals.c:86
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
void * palloc(Size size)
Definition: mcxt.c:950
uint8 * statusFlags
Definition: proc.h:331
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121

◆ GetMaxSnapshotSubxidCount()

int GetMaxSnapshotSubxidCount ( void  )

Definition at line 1983 of file procarray.c.

References TOTAL_MAX_CACHED_SUBXIDS.

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

1984 {
1985  return TOTAL_MAX_CACHED_SUBXIDS;
1986 }
#define TOTAL_MAX_CACHED_SUBXIDS

◆ GetMaxSnapshotXidCount()

int GetMaxSnapshotXidCount ( void  )

Definition at line 1972 of file procarray.c.

References ProcArrayStruct::maxProcs.

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

1973 {
1974  return procArray->maxProcs;
1975 }
static ProcArrayStruct * procArray
Definition: procarray.c:250

◆ GetOldestActiveTransactionId()

TransactionId GetOldestActiveTransactionId ( void  )

Definition at line 2785 of file procarray.c.

References Assert, LW_SHARED, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ProcArrayStruct::numProcs, procArray, ProcGlobal, RecoveryInProgress(), ShmemVariableCache, TransactionIdIsNormal, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, XidFromFullTransactionId, and PROC_HDR::xids.

Referenced by CreateCheckPoint().

2786 {
2787  ProcArrayStruct *arrayP = procArray;
2788  TransactionId *other_xids = ProcGlobal->xids;
2789  TransactionId oldestRunningXid;
2790  int index;
2791 
2793 
2794  /*
2795  * Read nextXid, as the upper bound of what's still active.
2796  *
2797  * Reading a TransactionId is atomic, but we must grab the lock to make
2798  * sure that all XIDs < nextXid are already present in the proc array (or
2799  * have already completed), when we spin over it.
2800  */
2801  LWLockAcquire(XidGenLock, LW_SHARED);
2803  LWLockRelease(XidGenLock);
2804 
2805  /*
2806  * Spin over procArray collecting all xids and subxids.
2807  */
2808  LWLockAcquire(ProcArrayLock, LW_SHARED);
2809  for (index = 0; index < arrayP->numProcs; index++)
2810  {
2811  TransactionId xid;
2812 
2813  /* Fetch xid just once - see GetNewTransactionId */
2814  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2815 
2816  if (!TransactionIdIsNormal(xid))
2817  continue;
2818 
2819  if (TransactionIdPrecedes(xid, oldestRunningXid))
2820  oldestRunningXid = xid;
2821 
2822  /*
2823  * Top-level XID of a transaction is always less than any of its
2824  * subxids, so we don't need to check if any of the subxids are
2825  * smaller than oldestRunningXid
2826  */
2827  }
2828  LWLockRelease(ProcArrayLock);
2829 
2830  return oldestRunningXid;
2831 }
uint32 TransactionId
Definition: c.h:575
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool RecoveryInProgress(void)
Definition: xlog.c:8148
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:319
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestNonRemovableTransactionId()

TransactionId GetOldestNonRemovableTransactionId ( Relation  rel)

Definition at line 1913 of file procarray.c.

References ComputeXidHorizonsResult::catalog_oldest_nonremovable, ComputeXidHorizons(), ComputeXidHorizonsResult::data_oldest_nonremovable, RelationData::rd_rel, RELATION_IS_LOCAL, RelationIsAccessibleInLogicalDecoding, ComputeXidHorizonsResult::shared_oldest_nonremovable, and ComputeXidHorizonsResult::temp_oldest_nonremovable.

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

1914 {
1915  ComputeXidHorizonsResult horizons;
1916 
1917  ComputeXidHorizons(&horizons);
1918 
1919  /* select horizon appropriate for relation */
1920  if (rel == NULL || rel->rd_rel->relisshared)
1921  return horizons.shared_oldest_nonremovable;
1923  return horizons.catalog_oldest_nonremovable;
1924  else if (RELATION_IS_LOCAL(rel))
1925  return horizons.temp_oldest_nonremovable;
1926  else
1927  return horizons.data_oldest_nonremovable;
1928 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1656
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:584
Form_pg_class rd_rel
Definition: rel.h:110
TransactionId catalog_oldest_nonremovable
Definition: procarray.c:233
TransactionId shared_oldest_nonremovable
Definition: procarray.c:216
#define RelationIsAccessibleInLogicalDecoding(relation)
Definition: rel.h:620
TransactionId temp_oldest_nonremovable
Definition: procarray.c:245
TransactionId data_oldest_nonremovable
Definition: procarray.c:239

◆ GetOldestSafeDecodingTransactionId()

TransactionId GetOldestSafeDecodingTransactionId ( bool  catalogOnly)

Definition at line 2850 of file procarray.c.

References Assert, LW_SHARED, LWLockAcquire(), LWLockHeldByMe(), LWLockRelease(), VariableCacheData::nextXid, ProcArrayStruct::numProcs, procArray, ProcGlobal, RecoveryInProgress(), ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), UINT32_ACCESS_ONCE, XidFromFullTransactionId, and PROC_HDR::xids.

Referenced by CreateInitDecodingContext(), and SnapBuildInitialSnapshot().

2851 {
2852  ProcArrayStruct *arrayP = procArray;
2853  TransactionId oldestSafeXid;
2854  int index;
2855  bool recovery_in_progress = RecoveryInProgress();
2856 
2857  Assert(LWLockHeldByMe(ProcArrayLock));
2858 
2859  /*
2860  * Acquire XidGenLock, so no transactions can acquire an xid while we're
2861  * running. If no transaction with xid were running concurrently a new xid
2862  * could influence the RecentXmin et al.
2863  *
2864  * We initialize the computation to nextXid since that's guaranteed to be
2865  * a safe, albeit pessimal, value.
2866  */
2867  LWLockAcquire(XidGenLock, LW_SHARED);
2869 
2870  /*
2871  * If there's already a slot pegging the xmin horizon, we can start with
2872  * that value, it's guaranteed to be safe since it's computed by this
2873  * routine initially and has been enforced since. We can always use the
2874  * slot's general xmin horizon, but the catalog horizon is only usable
2875  * when only catalog data is going to be looked at.
2876  */
2879  oldestSafeXid))
2880  oldestSafeXid = procArray->replication_slot_xmin;
2881 
2882  if (catalogOnly &&
2885  oldestSafeXid))
2886  oldestSafeXid = procArray->replication_slot_catalog_xmin;
2887 
2888  /*
2889  * If we're not in recovery, we walk over the procarray and collect the
2890  * lowest xid. Since we're called with ProcArrayLock held and have
2891  * acquired XidGenLock, no entries can vanish concurrently, since
2892  * ProcGlobal->xids[i] is only set with XidGenLock held and only cleared
2893  * with ProcArrayLock held.
2894  *
2895  * In recovery we can't lower the safe value besides what we've computed
2896  * above, so we'll have to wait a bit longer there. We unfortunately can
2897  * *not* use KnownAssignedXidsGetOldestXmin() since the KnownAssignedXids
2898  * machinery can miss values and return an older value than is safe.
2899  */
2900  if (!recovery_in_progress)
2901  {
2902  TransactionId *other_xids = ProcGlobal->xids;
2903 
2904  /*
2905  * Spin over procArray collecting min(ProcGlobal->xids[i])
2906  */
2907  for (index = 0; index < arrayP->numProcs; index++)
2908  {
2909  TransactionId xid;
2910 
2911  /* Fetch xid just once - see GetNewTransactionId */
2912  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2913 
2914  if (!TransactionIdIsNormal(xid))
2915  continue;
2916 
2917  if (TransactionIdPrecedes(xid, oldestSafeXid))
2918  oldestSafeXid = xid;
2919  }
2920  }
2921 
2922  LWLockRelease(XidGenLock);
2923 
2924  return oldestSafeXid;
2925 }
uint32 TransactionId
Definition: c.h:575
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1926
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool RecoveryInProgress(void)
Definition: xlog.c:8148
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:319
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ GetOldestTransactionIdConsideredRunning()

TransactionId GetOldestTransactionIdConsideredRunning ( void  )

Definition at line 1937 of file procarray.c.

References ComputeXidHorizons(), and ComputeXidHorizonsResult::oldest_considered_running.

Referenced by CreateCheckPoint(), and CreateRestartPoint().

1938 {
1939  ComputeXidHorizonsResult horizons;
1940 
1941  ComputeXidHorizons(&horizons);
1942 
1943  return horizons.oldest_considered_running;
1944 }
TransactionId oldest_considered_running
Definition: procarray.c:207
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1656

◆ GetReplicationHorizons()

void GetReplicationHorizons ( TransactionId slot_xmin,
TransactionId catalog_xmin 
)

Definition at line 1950 of file procarray.c.

References ComputeXidHorizons(), ComputeXidHorizonsResult::shared_oldest_nonremovable_raw, and ComputeXidHorizonsResult::slot_catalog_xmin.

Referenced by XLogWalRcvSendHSFeedback().

1951 {
1952  ComputeXidHorizonsResult horizons;
1953 
1954  ComputeXidHorizons(&horizons);
1955 
1956  /*
1957  * Don't want to use shared_oldest_nonremovable here, as that contains the
1958  * effect of replication slot's catalog_xmin. We want to send a separate
1959  * feedback for the catalog horizon, so the primary can remove data table
1960  * contents more aggressively.
1961  */
1962  *xmin = horizons.shared_oldest_nonremovable_raw;
1963  *catalog_xmin = horizons.slot_catalog_xmin;
1964 }
static void ComputeXidHorizons(ComputeXidHorizonsResult *h)
Definition: procarray.c:1656
TransactionId shared_oldest_nonremovable_raw
Definition: procarray.c:227
TransactionId slot_catalog_xmin
Definition: procarray.c:194

◆ GetRunningTransactionData()

RunningTransactions GetRunningTransactionData ( void  )

Definition at line 2610 of file procarray.c.

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

Referenced by LogStandbySnapshot().

2611 {
2612  /* result workspace */
2613  static RunningTransactionsData CurrentRunningXactsData;
2614 
2615  ProcArrayStruct *arrayP = procArray;
2616  TransactionId *other_xids = ProcGlobal->xids;
2617  RunningTransactions CurrentRunningXacts = &CurrentRunningXactsData;
2618  TransactionId latestCompletedXid;
2619  TransactionId oldestRunningXid;
2620  TransactionId *xids;
2621  int index;
2622  int count;
2623  int subcount;
2624  bool suboverflowed;
2625 
2627 
2628  /*
2629  * Allocating space for maxProcs xids is usually overkill; numProcs would
2630  * be sufficient. But it seems better to do the malloc while not holding
2631  * the lock, so we can't look at numProcs. Likewise, we allocate much
2632  * more subxip storage than is probably needed.
2633  *
2634  * Should only be allocated in bgwriter, since only ever executed during
2635  * checkpoints.
2636  */
2637  if (CurrentRunningXacts->xids == NULL)
2638  {
2639  /*
2640  * First call
2641  */
2642  CurrentRunningXacts->xids = (TransactionId *)
2644  if (CurrentRunningXacts->xids == NULL)
2645  ereport(ERROR,
2646  (errcode(ERRCODE_OUT_OF_MEMORY),
2647  errmsg("out of memory")));
2648  }
2649 
2650  xids = CurrentRunningXacts->xids;
2651 
2652  count = subcount = 0;
2653  suboverflowed = false;
2654 
2655  /*
2656  * Ensure that no xids enter or leave the procarray while we obtain
2657  * snapshot.
2658  */
2659  LWLockAcquire(ProcArrayLock, LW_SHARED);
2660  LWLockAcquire(XidGenLock, LW_SHARED);
2661 
2662  latestCompletedXid =
2664  oldestRunningXid =
2666 
2667  /*
2668  * Spin over procArray collecting all xids
2669  */
2670  for (index = 0; index < arrayP->numProcs; index++)
2671  {
2672  TransactionId xid;
2673 
2674  /* Fetch xid just once - see GetNewTransactionId */
2675  xid = UINT32_ACCESS_ONCE(other_xids[index]);
2676 
2677  /*
2678  * We don't need to store transactions that don't have a TransactionId
2679  * yet because they will not show as running on a standby server.
2680  */
2681  if (!TransactionIdIsValid(xid))
2682  continue;
2683 
2684  /*
2685  * Be careful not to exclude any xids before calculating the values of
2686  * oldestRunningXid and suboverflowed, since these are used to clean
2687  * up transaction information held on standbys.
2688  */
2689  if (TransactionIdPrecedes(xid, oldestRunningXid))
2690  oldestRunningXid = xid;
2691 
2692  if (ProcGlobal->subxidStates[index].overflowed)
2693  suboverflowed = true;
2694 
2695  /*
2696  * If we wished to exclude xids this would be the right place for it.
2697  * Procs with the PROC_IN_VACUUM flag set don't usually assign xids,
2698  * but they do during truncation at the end when they get the lock and
2699  * truncate, so it is not much of a problem to include them if they
2700  * are seen and it is cleaner to include them.
2701  */
2702 
2703  xids[count++] = xid;
2704  }
2705 
2706  /*
2707  * Spin over procArray collecting all subxids, but only if there hasn't
2708  * been a suboverflow.
2709  */
2710  if (!suboverflowed)
2711  {
2712  XidCacheStatus *other_subxidstates = ProcGlobal->subxidStates;
2713 
2714  for (index = 0; index < arrayP->numProcs; index++)
2715  {
2716  int pgprocno = arrayP->pgprocnos[index];
2717  PGPROC *proc = &allProcs[pgprocno];
2718  int nsubxids;
2719 
2720  /*
2721  * Save subtransaction XIDs. Other backends can't add or remove
2722  * entries while we're holding XidGenLock.
2723  */
2724  nsubxids = other_subxidstates[index].count;
2725  if (nsubxids > 0)
2726  {
2727  /* barrier not really required, as XidGenLock is held, but ... */
2728  pg_read_barrier(); /* pairs with GetNewTransactionId */
2729 
2730  memcpy(&xids[count], (void *) proc->subxids.xids,
2731  nsubxids * sizeof(TransactionId));
2732  count += nsubxids;
2733  subcount += nsubxids;
2734 
2735  /*
2736  * Top-level XID of a transaction is always less than any of
2737  * its subxids, so we don't need to check if any of the
2738  * subxids are smaller than oldestRunningXid
2739  */
2740  }
2741  }
2742  }
2743 
2744  /*
2745  * It's important *not* to include the limits set by slots here because
2746  * snapbuild.c uses oldestRunningXid to manage its xmin horizon. If those
2747  * were to be included here the initial value could never increase because
2748  * of a circular dependency where slots only increase their limits when
2749  * running xacts increases oldestRunningXid and running xacts only
2750  * increases if slots do.
2751  */
2752 
2753  CurrentRunningXacts->xcnt = count - subcount;
2754  CurrentRunningXacts->subxcnt = subcount;
2755  CurrentRunningXacts->subxid_overflow = suboverflowed;
2757  CurrentRunningXacts->oldestRunningXid = oldestRunningXid;
2758  CurrentRunningXacts->latestCompletedXid = latestCompletedXid;
2759 
2760  Assert(TransactionIdIsValid(CurrentRunningXacts->nextXid));
2761  Assert(TransactionIdIsValid(CurrentRunningXacts->oldestRunningXid));
2762  Assert(TransactionIdIsNormal(CurrentRunningXacts->latestCompletedXid));
2763 
2764  /* We don't release the locks here, the caller is responsible for that */
2765 
2766  return CurrentRunningXacts;
2767 }
TransactionId oldestRunningXid
Definition: standby.h:80
uint32 TransactionId
Definition: c.h:575
XidCacheStatus * subxidStates
Definition: proc.h:325
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
int errcode(int sqlerrcode)
Definition: elog.c:704
PROC_HDR * ProcGlobal
Definition: proc.c:80
TransactionId * xids
Definition: standby.h:83
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8148
FullTransactionId nextXid
Definition: transam.h:213
bool overflowed
Definition: proc.h:43
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId latestCompletedXid
Definition: standby.h:81
Definition: type.h:89
#define malloc(a)
Definition: header.h:50
#define ERROR
Definition: elog.h:45
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
struct XidCache subxids
Definition: proc.h:210
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:155
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:792
#define pg_read_barrier()
Definition: atomics.h:158
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
uint8 count
Definition: proc.h:41
TransactionId nextXid
Definition: standby.h:79
int errmsg(const char *fmt,...)
Definition: elog.c:915
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:121

◆ GetSnapshotData()

Snapshot GetSnapshotData ( Snapshot  snapshot)

Definition at line 2109 of file procarray.c.

References SnapshotData::active_count, Assert, SnapshotData::copied, XidCacheStatus::count, SnapshotData::curcid, GlobalVisState::definitely_needed, ereport, errcode(), errmsg(), ERROR, FullTransactionIdAdvance(), FullTransactionIdNewer(), FullXidRelativeTo(), GetCurrentCommandId(), GetMaxSnapshotSubxidCount(), GetMaxSnapshotXidCount(), GetSnapshotDataInitOldSnapshot(), GetSnapshotDataReuse(), InvalidTransactionId, KnownAssignedXidsGetAndSetXmin(), ProcArrayStruct::lastOverflowedXid, VariableCacheData::latestCompletedXid, likely, LW_SHARED, LWLockAcquire(), LWLockRelease(), malloc, GlobalVisState::maybe_needed, MyProc, NormalTransactionIdPrecedes, ProcArrayStruct::numProcs, VariableCacheData::oldestXid, pg_read_barrier, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, PROC_IN_LOGICAL_DECODING, PROC_IN_VACUUM, procArray, ProcGlobal, RecentXmin, RecoveryInProgress(), SnapshotData::regd_count, ProcArrayStruct::replication_slot_catalog_xmin, ProcArrayStruct::replication_slot_xmin, ShmemVariableCache, SnapshotData::snapXactCompletionCount, PROC_HDR::statusFlags, SnapshotData::suboverflowed, SnapshotData::subxcnt, PGPROC::subxids, PROC_HDR::subxidStates, SnapshotData::subxip, SnapshotData::takenDuringRecovery, TransactionIdAdvance, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdOlder(), TransactionIdPrecedesOrEquals(), TransactionIdRetreatedBy(), TransactionXmin, UINT32_ACCESS_ONCE, vacuum_defer_cleanup_age, VariableCacheData::xactCompletionCount, SnapshotData::xcnt, PGPROC::xid, XidFromFullTransactionId, XidCache::xids, PROC_HDR::xids, SnapshotData::xip, SnapshotData::xmax, PGPROC::xmin, and SnapshotData::xmin.

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

2110 {
2111  ProcArrayStruct *arrayP = procArray;
2112  TransactionId *other_xids = ProcGlobal->xids;
2113  TransactionId xmin;
2114  TransactionId xmax;
2115  size_t count = 0;
2116  int subcount = 0;
2117  bool suboverflowed = false;
2118  FullTransactionId latest_completed;
2119  TransactionId oldestxid;
2120  int mypgxactoff;
2121  TransactionId myxid;
2122  uint64 curXactCompletionCount;
2123 
2124  TransactionId replication_slot_xmin = InvalidTransactionId;
2125  TransactionId replication_slot_catalog_xmin = InvalidTransactionId;
2126 
2127  Assert(snapshot != NULL);
2128 
2129  /*
2130  * Allocating space for maxProcs xids is usually overkill; numProcs would
2131  * be sufficient. But it seems better to do the malloc while not holding
2132  * the lock, so we can't look at numProcs. Likewise, we allocate much
2133  * more subxip storage than is probably needed.
2134  *
2135  * This does open a possibility for avoiding repeated malloc/free: since
2136  * maxProcs does not change at runtime, we can simply reuse the previous
2137  * xip arrays if any. (This relies on the fact that all callers pass
2138  * static SnapshotData structs.)
2139  */
2140  if (snapshot->xip == NULL)
2141  {
2142  /*
2143  * First call for this snapshot. Snapshot is same size whether or not
2144  * we are in recovery, see later comments.
2145  */
2146  snapshot->xip = (TransactionId *)
2148  if (snapshot->xip == NULL)
2149  ereport(ERROR,
2150  (errcode(ERRCODE_OUT_OF_MEMORY),
2151  errmsg("out of memory")));
2152  Assert(snapshot->subxip == NULL);
2153  snapshot->subxip = (TransactionId *)
2155  if (snapshot->subxip == NULL)
2156  ereport(ERROR,
2157  (errcode(ERRCODE_OUT_OF_MEMORY),
2158  errmsg("out of memory")));
2159  }
2160 
2161  /*
2162  * It is sufficient to get shared lock on ProcArrayLock, even if we are
2163  * going to set MyProc->xmin.
2164  */
2165  LWLockAcquire(ProcArrayLock, LW_SHARED);
2166 
2167  if (GetSnapshotDataReuse(snapshot))
2168  {
2169  LWLockRelease(ProcArrayLock);
2170  return snapshot;
2171  }
2172 
2173  latest_completed = ShmemVariableCache->latestCompletedXid;
2174  mypgxactoff = MyProc->pgxactoff;
2175  myxid = other_xids[mypgxactoff];
2176  Assert(myxid == MyProc->xid);
2177 
2178  oldestxid = ShmemVariableCache->oldestXid;
2179  curXactCompletionCount = ShmemVariableCache->xactCompletionCount;
2180 
2181  /* xmax is always latestCompletedXid + 1 */
2182  xmax = XidFromFullTransactionId(latest_completed);
2183  TransactionIdAdvance(xmax);
2185 
2186  /* initialize xmin calculation with xmax */
2187  xmin = xmax;
2188 
2189  /* take own xid into account, saves a check inside the loop */
2190  if (TransactionIdIsNormal(myxid) && NormalTransactionIdPrecedes(myxid, xmin))
2191  xmin = myxid;
2192 
2194 
2195  if (!snapshot->takenDuringRecovery)
2196  {
2197  size_t numProcs = arrayP->numProcs;
2198  TransactionId *xip = snapshot->xip;
2199  int *pgprocnos = arrayP->pgprocnos;
2200  XidCacheStatus *subxidStates = ProcGlobal->subxidStates;
2201  uint8 *allStatusFlags = ProcGlobal->statusFlags;
2202 
2203  /*
2204  * First collect set of pgxactoff/xids that need to be included in the
2205  * snapshot.
2206  */
2207  for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
2208  {
2209  /* Fetch xid just once - see GetNewTransactionId */
2210  TransactionId xid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
2211  uint8 statusFlags;
2212 
2213  Assert(allProcs[arrayP->pgprocnos[pgxactoff]].pgxactoff == pgxactoff);
2214 
2215  /*
2216  * If the transaction has no XID assigned, we can skip it; it
2217  * won't have sub-XIDs either.
2218  */
2219  if (likely(xid == InvalidTransactionId))
2220  continue;
2221 
2222  /*
2223  * We don't include our own XIDs (if any) in the snapshot. It
2224  * needs to be includeded in the xmin computation, but we did so
2225  * outside the loop.
2226  */
2227  if (pgxactoff == mypgxactoff)
2228  continue;
2229 
2230  /*
2231  * The only way we are able to get here with a non-normal xid
2232  * is during bootstrap - with this backend using
2233  * BootstrapTransactionId. But the above test should filter
2234  * that out.
2235  */
2237 
2238  /*
2239  * If the XID is >= xmax, we can skip it; such transactions will
2240  * be treated as running anyway (and any sub-XIDs will also be >=
2241  * xmax).
2242  */
2243  if (!NormalTransactionIdPrecedes(xid, xmax))
2244  continue;
2245 
2246  /*
2247  * Skip over backends doing logical decoding which manages xmin
2248  * separately (check below) and ones running LAZY VACUUM.
2249  */
2250  statusFlags = allStatusFlags[pgxactoff];
2251  if (statusFlags & (PROC_IN_LOGICAL_DECODING | PROC_IN_VACUUM))
2252  continue;
2253 
2254  if (NormalTransactionIdPrecedes(xid, xmin))
2255  xmin = xid;
2256 
2257  /* Add XID to snapshot. */
2258  xip[count++] = xid;
2259 
2260  /*
2261  * Save subtransaction XIDs if possible (if we've already
2262  * overflowed, there's no point). Note that the subxact XIDs must
2263  * be later than their parent, so no need to check them against
2264  * xmin. We could filter against xmax, but it seems better not to
2265  * do that much work while holding the ProcArrayLock.
2266  *
2267  * The other backend can add more subxids concurrently, but cannot
2268  * remove any. Hence it's important to fetch nxids just once.
2269  * Should be safe to use memcpy, though. (We needn't worry about
2270  * missing any xids added concurrently, because they must postdate
2271  * xmax.)
2272  *
2273  * Again, our own XIDs are not included in the snapshot.
2274  */
2275  if (!suboverflowed)
2276  {
2277 
2278  if (subxidStates[pgxactoff].overflowed)
2279  suboverflowed = true;
2280  else
2281  {
2282  int nsubxids = subxidStates[pgxactoff].count;
2283 
2284  if (nsubxids > 0)
2285  {
2286  int pgprocno = pgprocnos[pgxactoff];
2287  PGPROC *proc = &allProcs[pgprocno];
2288 
2289  pg_read_barrier(); /* pairs with GetNewTransactionId */
2290 
2291  memcpy(snapshot->subxip + subcount,
2292  (void *) proc->subxids.xids,
2293  nsubxids * sizeof(TransactionId));
2294  subcount += nsubxids;
2295  }
2296  }
2297  }
2298  }
2299  }
2300  else
2301  {
2302  /*
2303  * We're in hot standby, so get XIDs from KnownAssignedXids.
2304  *
2305  * We store all xids directly into subxip[]. Here's why:
2306  *
2307  * In recovery we don't know which xids are top-level and which are
2308  * subxacts, a design choice that greatly simplifies xid processing.
2309  *
2310  * It seems like we would want to try to put xids into xip[] only, but
2311  * that is fairly small. We would either need to make that bigger or
2312  * to increase the rate at which we WAL-log xid assignment; neither is
2313  * an appealing choice.
2314  *
2315  * We could try to store xids into xip[] first and then into subxip[]
2316  * if there are too many xids. That only works if the snapshot doesn't
2317  * overflow because we do not search subxip[] in that case. A simpler
2318  * way is to just store all xids in the subxact array because this is
2319  * by far the bigger array. We just leave the xip array empty.
2320  *
2321  * Either way we need to change the way XidInMVCCSnapshot() works
2322  * depending upon when the snapshot was taken, or change normal
2323  * snapshot processing so it matches.
2324  *
2325  * Note: It is possible for recovery to end before we finish taking
2326  * the snapshot, and for newly assigned transaction ids to be added to
2327  * the ProcArray. xmax cannot change while we hold ProcArrayLock, so
2328  * those newly added transaction ids would be filtered away, so we
2329  * need not be concerned about them.
2330  */
2331  subcount = KnownAssignedXidsGetAndSetXmin(snapshot->subxip, &xmin,
2332  xmax);
2333 
2335  suboverflowed = true;
2336  }
2337 
2338 
2339  /*
2340  * Fetch into local variable while ProcArrayLock is held - the
2341  * LWLockRelease below is a barrier, ensuring this happens inside the
2342  * lock.
2343  */
2344  replication_slot_xmin = procArray->replication_slot_xmin;
2345  replication_slot_catalog_xmin = procArray->replication_slot_catalog_xmin;
2346 
2348  MyProc->xmin = TransactionXmin = xmin;
2349 
2350  LWLockRelease(ProcArrayLock);
2351 
2352  /* maintain state for GlobalVis* */
2353  {
2354  TransactionId def_vis_xid;
2355  TransactionId def_vis_xid_data;
2356  FullTransactionId def_vis_fxid;
2357  FullTransactionId def_vis_fxid_data;
2358  FullTransactionId oldestfxid;
2359 
2360  /*
2361  * Converting oldestXid is only safe when xid horizon cannot advance,
2362  * i.e. holding locks. While we don't hold the lock anymore, all the
2363  * necessary data has been gathered with lock held.
2364  */
2365  oldestfxid = FullXidRelativeTo(latest_completed, oldestxid);
2366 
2367  /* apply vacuum_defer_cleanup_age */
2368  def_vis_xid_data =
2370 
2371  /* Check whether there's a replication slot requiring an older xmin. */
2372  def_vis_xid_data =
2373  TransactionIdOlder(def_vis_xid_data, replication_slot_xmin);
2374 
2375  /*
2376  * Rows in non-shared, non-catalog tables possibly could be vacuumed
2377  * if older than this xid.
2378  */
2379  def_vis_xid = def_vis_xid_data;
2380 
2381  /*
2382  * Check whether there's a replication slot requiring an older catalog
2383  * xmin.
2384  */
2385  def_vis_xid =
2386  TransactionIdOlder(replication_slot_catalog_xmin, def_vis_xid);
2387 
2388  def_vis_fxid = FullXidRelativeTo(latest_completed, def_vis_xid);
2389  def_vis_fxid_data = FullXidRelativeTo(latest_completed, def_vis_xid_data);
2390 
2391  /*
2392  * Check if we can increase upper bound. As a previous
2393  * GlobalVisUpdate() might have computed more aggressive values, don't
2394  * overwrite them if so.
2395  */
2397  FullTransactionIdNewer(def_vis_fxid,
2400  FullTransactionIdNewer(def_vis_fxid,
2403  FullTransactionIdNewer(def_vis_fxid_data,
2405  /* See temp_oldest_nonremovable computation in ComputeXidHorizons() */
2406  if (TransactionIdIsNormal(myxid))
2408  FullXidRelativeTo(latest_completed, myxid);
2409  else
2410  {
2411  GlobalVisTempRels.definitely_needed = latest_completed;
2413  }
2414 
2415  /*
2416  * Check if we know that we can initialize or increase the lower
2417  * bound. Currently the only cheap way to do so is to use
2418  * ShmemVariableCache->oldestXid as input.
2419  *
2420  * We should definitely be able to do better. We could e.g. put a
2421  * global lower bound value into ShmemVariableCache.
2422  */
2425  oldestfxid);
2428  oldestfxid);
2431  oldestfxid);
2432  /* accurate value known */
2434  }
2435 
2436  RecentXmin = xmin;
2438 
2439  snapshot->xmin = xmin;
2440  snapshot->xmax = xmax;
2441  snapshot->xcnt = count;
2442  snapshot->subxcnt = subcount;
2443  snapshot->suboverflowed = suboverflowed;
2444  snapshot->snapXactCompletionCount = curXactCompletionCount;
2445 
2446  snapshot->curcid = GetCurrentCommandId(false);
2447 
2448  /*
2449  * This is a new snapshot, so set both refcounts are zero, and mark it as
2450  * not copied in persistent memory.
2451  */
2452  snapshot->active_count = 0;
2453  snapshot->regd_count = 0;
2454  snapshot->copied = false;
2455 
2457 
2458  return snapshot;
2459 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
uint64 snapXactCompletionCount
Definition: snapshot.h:216
#define likely(x)
Definition: c.h:260
#define PROC_IN_LOGICAL_DECODING
Definition: proc.h:61
uint32 TransactionId
Definition: c.h:575
bool copied
Definition: snapshot.h:185
XidCacheStatus * subxidStates
Definition: proc.h:325
PGPROC * MyProc
Definition: proc.c:68
int vacuum_defer_cleanup_age
Definition: standby.c:39
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
unsigned char uint8
Definition: c.h:427
static FullTransactionId FullXidRelativeTo(FullTransactionId rel, TransactionId xid)
Definition: procarray.c:4184
TransactionId oldestXid
Definition: transam.h:215
int errcode(int sqlerrcode)
Definition: elog.c:704
TransactionId RecentXmin
Definition: snapmgr.c:113
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:80
bool suboverflowed
Definition: snapshot.h:182
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8148
uint32 regd_count
Definition: snapshot.h:205
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransactionId TransactionXmin
Definition: snapmgr.c:112
FullTransactionId definitely_needed
Definition: procarray.c:172
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
static void GetSnapshotDataInitOldSnapshot(Snapshot snapshot)
Definition: procarray.c:1992
#define PROC_IN_VACUUM
Definition: proc.h:55
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:45
TransactionId xmin
Definition: proc.h:138
static GlobalVisState GlobalVisSharedRels
Definition: procarray.c:273
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
TransactionId xmax
Definition: snapshot.h:158
TransactionId xmin
Definition: snapshot.h:157
struct XidCache subxids
Definition: proc.h:210
TransactionId lastOverflowedXid
Definition: procarray.c:93
TransactionId * xip
Definition: snapshot.h:168
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
CommandId curcid
Definition: snapshot.h:187
#define ereport(elevel,...)
Definition: elog.h:155
int GetMaxSnapshotXidCount(void)
Definition: procarray.c:1972
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
static TransactionId TransactionIdOlder(TransactionId a, TransactionId b)
Definition: transam.h:327
#define Assert(condition)
Definition: c.h:792
#define pg_read_barrier()
Definition: atomics.h:158
bool takenDuringRecovery
Definition: snapshot.h:184
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
static TransactionId TransactionIdRetreatedBy(TransactionId xid, uint32 amount)
Definition: transam.h:315
static int KnownAssignedXidsGetAndSetXmin(TransactionId *xarray, TransactionId *xmin, TransactionId xmax)
Definition: procarray.c:4904
#define NormalTransactionIdPrecedes(id1, id2)
Definition: transam.h:147
FullTransactionId maybe_needed
Definition: procarray.c:175
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:133
static FullTransactionId FullTransactionIdNewer(FullTransactionId a, FullTransactionId b)
Definition: transam.h:353
static GlobalVisState GlobalVisTempRels
Definition: procarray.c:276
uint32 xcnt
Definition: snapshot.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:915
int pgxactoff
Definition: proc.h:148
static bool GetSnapshotDataReuse(Snapshot snapshot)
Definition: procarray.c:2026
int GetMaxSnapshotSubxidCount(void)
Definition: procarray.c:1983
CommandId GetCurrentCommandId(bool used)
Definition: xact.c:761
uint8 * statusFlags
Definition: proc.h:331
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static GlobalVisState GlobalVisCatalogRels
Definition: procarray.c:274
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static GlobalVisState GlobalVisDataRels
Definition: procarray.c:275
Definition: proc.h:121
static void FullTransactionIdAdvance(FullTransactionId *dest)
Definition: transam.h:128
TransactionId * subxip
Definition: snapshot.h:180
uint32 active_count
Definition: snapshot.h:204
int32 subxcnt
Definition: snapshot.h:181

◆ GetVirtualXIDsDelayingChkpt()

VirtualTransactionId* GetVirtualXIDsDelayingChkpt ( int *  nvxids)

Definition at line 2946 of file procarray.c.

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

Referenced by CreateCheckPoint().

2947 {
2948  VirtualTransactionId *vxids;
2949  ProcArrayStruct *arrayP = procArray;
2950  int count = 0;
2951  int index;
2952 
2953  /* allocate what's certainly enough result space */
2954  vxids = (VirtualTransactionId *)
2955  palloc(sizeof(VirtualTransactionId) * arrayP->maxProcs);
2956 
2957  LWLockAcquire(ProcArrayLock, LW_SHARED);
2958 
2959  for (index = 0; index < arrayP->numProcs; index++)
2960  {
2961  int pgprocno = arrayP->pgprocnos[index];
2962  PGPROC *proc = &allProcs[pgprocno];
2963 
2964  if (proc->delayChkpt)
2965  {
2966  VirtualTransactionId vxid;
2967 
2968  GET_VXID_FROM_PGPROC(vxid, *proc);
2969  if (VirtualTransactionIdIsValid(vxid))
2970  vxids[count++] = vxid;
2971  }
2972  }
2973 
2974  LWLockRelease(ProcArrayLock);
2975 
2976  *nvxids = count;
2977  return vxids;
2978 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool delayChkpt
Definition: proc.h:185
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
void * palloc(Size size)
Definition: mcxt.c:950
Definition: proc.h:121

◆ HaveVirtualXIDsDelayingChkpt()

bool HaveVirtualXIDsDelayingChkpt ( VirtualTransactionId vxids,
int  nvxids 
)

Definition at line 2990 of file procarray.c.

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

Referenced by CreateCheckPoint().

2991 {
2992  bool result = false;
2993  ProcArrayStruct *arrayP = procArray;
2994  int index;
2995 
2996  LWLockAcquire(ProcArrayLock, LW_SHARED);
2997 
2998  for (index = 0; index < arrayP->numProcs; index++)
2999  {
3000  int pgprocno = arrayP->pgprocnos[index];
3001  PGPROC *proc = &allProcs[pgprocno];
3002  VirtualTransactionId vxid;
3003 
3004  GET_VXID_FROM_PGPROC(vxid, *proc);
3005 
3006  if (proc->delayChkpt && VirtualTransactionIdIsValid(vxid))
3007  {
3008  int i;
3009 
3010  for (i = 0; i < nvxids; i++)
3011  {
3012  if (VirtualTransactionIdEquals(vxid, vxids[i]))
3013  {
3014  result = true;
3015  break;
3016  }
3017  }
3018  if (result)
3019  break;
3020  }
3021  }
3022 
3023  LWLockRelease(ProcArrayLock);
3024 
3025  return result;
3026 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define VirtualTransactionIdEquals(vxid1, vxid2)
Definition: lock.h:73
bool delayChkpt
Definition: proc.h:185
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define VirtualTransactionIdIsValid(vxid)
Definition: lock.h:70
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
int i
Definition: proc.h:121

◆ IsBackendPid()

bool IsBackendPid ( int  pid)

Definition at line 3131 of file procarray.c.

References BackendPidGetProc().

Referenced by pg_stat_get_subscription().

3132 {
3133  return (BackendPidGetProc(pid) != NULL);
3134 }
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3036

◆ MinimumActiveBackends()

bool MinimumActiveBackends ( int  min)

Definition at line 3381 of file procarray.c.

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

Referenced by XLogFlush().

3382 {
3383  ProcArrayStruct *arrayP = procArray;
3384  int count = 0;
3385  int index;
3386 
3387  /* Quick short-circuit if no minimum is specified */
3388  if (min == 0)
3389  return true;
3390 
3391  /*
3392  * Note: for speed, we don't acquire ProcArrayLock. This is a little bit
3393  * bogus, but since we are only testing fields for zero or nonzero, it
3394  * should be OK. The result is only used for heuristic purposes anyway...
3395  */
3396  for (index = 0; index < arrayP->numProcs; index++)
3397  {
3398  int pgprocno = arrayP->pgprocnos[index];
3399  PGPROC *proc = &allProcs[pgprocno];
3400 
3401  /*
3402  * Since we're not holding a lock, need to be prepared to deal with
3403  * garbage, as someone could have incremented numProcs but not yet
3404  * filled the structure.
3405  *
3406  * If someone just decremented numProcs, 'proc' could also point to a
3407  * PGPROC entry that's no longer in the array. It still points to a
3408  * PGPROC struct, though, because freed PGPROC entries just go to the
3409  * free list and are recycled. Its contents are nonsense in that case,
3410  * but that's acceptable for this function.
3411  */
3412  if (pgprocno == -1)
3413  continue; /* do not count deleted entries */
3414  if (proc == MyProc)
3415  continue; /* do not count myself */
3416  if (proc->xid == InvalidTransactionId)
3417  continue; /* do not count if no XID assigned */
3418  if (proc->pid == 0)
3419  continue; /* do not count prepared xacts */
3420  if (proc->waitLock != NULL)
3421  continue; /* do not count if blocked on a lock */
3422  count++;
3423  if (count >= min)
3424  break;
3425  }
3426 
3427  return count >= min;
3428 }
PGPROC * MyProc
Definition: proc.c:68
Definition: type.h:89
#define InvalidTransactionId
Definition: transam.h:31
static PGPROC * allProcs
Definition: procarray.c:252
LOCK * waitLock
Definition: proc.h:179
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xid
Definition: proc.h:133
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ ProcArrayAdd()

void ProcArrayAdd ( PGPROC proc)

Definition at line 445 of file procarray.c.

References ereport, errcode(), errmsg(), FATAL, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcArrayStruct::maxProcs, ProcArrayStruct::numProcs, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, procArray, ProcGlobal, PGPROC::statusFlags, PROC_HDR::statusFlags, PROC_HDR::subxidStates, PGPROC::subxidStatus, PGPROC::xid, and PROC_HDR::xids.

Referenced by InitProcessPhase2(), and MarkAsPrepared().

446 {
447  ProcArrayStruct *arrayP = procArray;
448  int index;
449 
450  /* See ProcGlobal comment explaining why both locks are held */
451  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
452  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
453 
454  if (arrayP->numProcs >= arrayP->maxProcs)
455  {
456  /*
457  * Oops, no room. (This really shouldn't happen, since there is a
458  * fixed supply of PGPROC structs too, and so we should have failed
459  * earlier.)
460  */
461  ereport(FATAL,
462  (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
463  errmsg("sorry, too many clients already")));
464  }
465 
466  /*
467  * Keep the procs array sorted by (PGPROC *) so that we can utilize
468  * locality of references much better. This is useful while traversing the
469  * ProcArray because there is an increased likelihood of finding the next
470  * PGPROC structure in the cache.
471  *
472  * Since the occurrence of adding/removing a proc is much lower than the
473  * access to the ProcArray itself, the overhead should be marginal
474  */
475  for (index = 0; index < arrayP->numProcs; index++)
476  {
477  /*
478  * If we are the first PGPROC or if we have found our right position
479  * in the array, break
480  */
481  if ((arrayP->pgprocnos[index] == -1) || (arrayP->pgprocnos[index] > proc->pgprocno))
482  break;
483  }
484 
485  memmove(&arrayP->pgprocnos[index + 1], &arrayP->pgprocnos[index],
486  (arrayP->numProcs - index) * sizeof(*arrayP->pgprocnos));
487  memmove(&ProcGlobal->xids[index + 1], &ProcGlobal->xids[index],
488  (arrayP->numProcs - index) * sizeof(*ProcGlobal->xids));
489  memmove(&ProcGlobal->subxidStates[index + 1], &ProcGlobal->subxidStates[index],
490  (arrayP->numProcs - index) * sizeof(*ProcGlobal->subxidStates));
491  memmove(&ProcGlobal->statusFlags[index + 1], &ProcGlobal->statusFlags[index],
492  (arrayP->numProcs - index) * sizeof(*ProcGlobal->statusFlags));
493 
494  arrayP->pgprocnos[index] = proc->pgprocno;
495  ProcGlobal->xids[index] = proc->xid;
496  ProcGlobal->subxidStates[index] = proc->subxidStatus;
497  ProcGlobal->statusFlags[index] = proc->statusFlags;
498 
499  arrayP->numProcs++;
500 
501  for (; index < arrayP->numProcs; index++)
502  {
503  allProcs[arrayP->pgprocnos[index]].pgxactoff = index;
504  }
505 
506  /*
507  * Release in reversed acquisition order, to reduce frequency of having to
508  * wait for XidGenLock while holding ProcArrayLock.
509  */
510  LWLockRelease(XidGenLock);
511  LWLockRelease(ProcArrayLock);
512 }
XidCacheStatus * subxidStates
Definition: proc.h:325
int errcode(int sqlerrcode)
Definition: elog.c:704
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 statusFlags
Definition: proc.h:187
XidCacheStatus subxidStatus
Definition: proc.h:208
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define FATAL
Definition: elog.h:54
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:155
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
TransactionId xid
Definition: proc.h:133
int pgprocno
Definition: proc.h:150
int errmsg(const char *fmt,...)
Definition: elog.c:915
int pgxactoff
Definition: proc.h:148
uint8 * statusFlags
Definition: proc.h:331

◆ ProcArrayApplyRecoveryInfo()

void ProcArrayApplyRecoveryInfo ( RunningTransactions  running)

Definition at line 1000 of file procarray.c.

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

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

1001 {
1002  TransactionId *xids;
1003  int nxids;
1004  int i;
1005 
1007  Assert(TransactionIdIsValid(running->nextXid));
1010 
1011  /*
1012  * Remove stale transactions, if any.
1013  */
1015 
1016  /*
1017  * Remove stale locks, if any.
1018  */
1020 
1021  /*
1022  * If our snapshot is already valid, nothing else to do...
1023  */
1025  return;
1026 
1027  /*
1028  * If our initial RunningTransactionsData had an overflowed snapshot then
1029  * we knew we were missing some subxids from our snapshot. If we continue
1030  * to see overflowed snapshots then we might never be able to start up, so
1031  * we make another test to see if our snapshot is now valid. We know that
1032  * the missing subxids are equal to or earlier than nextXid. After we
1033  * initialise we continue to apply changes during recovery, so once the
1034  * oldestRunningXid is later than the nextXid from the initial snapshot we
1035  * know that we no longer have missing information and can mark the
1036  * snapshot as valid.
1037  */
1039  {
1040  /*
1041  * If the snapshot isn't overflowed or if its empty we can reset our
1042  * pending state and use this snapshot instead.
1043  */
1044  if (!running->subxid_overflow || running->xcnt == 0)
1045  {
1046  /*
1047  * If we have already collected known assigned xids, we need to
1048  * throw them away before we apply the recovery snapshot.
1049  */
1052  }
1053  else
1054  {
1056  running->oldestRunningXid))
1057  {
1060  "recovery snapshots are now enabled");
1061  }
1062  else
1064  "recovery snapshot waiting for non-overflowed snapshot or "
1065  "until oldest active xid on standby is at least %u (now %u)",
1067  running->oldestRunningXid);
1068  return;
1069  }
1070  }
1071 
1073 
1074  /*
1075  * NB: this can be reached at least twice, so make sure new code can deal
1076  * with that.
1077  */
1078 
1079  /*
1080  * Nobody else is running yet, but take locks anyhow
1081  */
1082  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1083 
1084  /*
1085  * KnownAssignedXids is sorted so we cannot just add the xids, we have to
1086  * sort them first.
1087  *
1088  * Some of the new xids are top-level xids and some are subtransactions.
1089  * We don't call SubTransSetParent because it doesn't matter yet. If we
1090  * aren't overflowed then all xids will fit in snapshot and so we don't
1091  * need subtrans. If we later overflow, an xid assignment record will add
1092  * xids to subtrans. If RunningTransactionsData is overflowed then we
1093  * don't have enough information to correctly update subtrans anyway.
1094  */
1095 
1096  /*
1097  * Allocate a temporary array to avoid modifying the array passed as
1098  * argument.
1099  */
1100  xids = palloc(sizeof(TransactionId) * (running->xcnt + running->subxcnt));
1101 
1102  /*
1103  * Add to the temp array any xids which have not already completed.
1104  */
1105  nxids = 0;
1106  for (i = 0; i < running->xcnt + running->subxcnt; i++)
1107  {
1108  TransactionId xid = running->xids[i];
1109 
1110  /*
1111  * The running-xacts snapshot can contain xids that were still visible
1112  * in the procarray when the snapshot was taken, but were already
1113  * WAL-logged as completed. They're not running anymore, so ignore
1114  * them.
1115  */
1117  continue;
1118 
1119  xids[nxids++] = xid;
1120  }
1121 
1122  if (nxids > 0)
1123  {
1124  if (procArray->numKnownAssignedXids != 0)
1125  {
1126  LWLockRelease(ProcArrayLock);
1127  elog(ERROR, "KnownAssignedXids is not empty");
1128  }
1129 
1130  /*
1131  * Sort the array so that we can add them safely into
1132  * KnownAssignedXids.
1133  */
1134  qsort(xids, nxids, sizeof(TransactionId), xidComparator);
1135 
1136  /*
1137  * Add the sorted snapshot into KnownAssignedXids. The running-xacts
1138  * snapshot may include duplicated xids because of prepared
1139  * transactions, so ignore them.
1140  */
1141  for (i = 0; i < nxids; i++)
1142  {
1143  if (i > 0 && TransactionIdEquals(xids[i - 1], xids[i]))
1144  {
1145  elog(DEBUG1,
1146  "found duplicated transaction %u for KnownAssignedXids insertion",
1147  xids[i]);
1148  continue;
1149  }
1150  KnownAssignedXidsAdd(xids[i], xids[i], true);
1151  }
1152 
1154  }
1155 
1156  pfree(xids);
1157 
1158  /*
1159  * latestObservedXid is at least set to the point where SUBTRANS was
1160  * started up to (cf. ProcArrayInitRecovery()) or to the biggest xid
1161  * RecordKnownAssignedTransactionIds() was called for. Initialize
1162  * subtrans from thereon, up to nextXid - 1.
1163  *
1164  * We need to duplicate parts of RecordKnownAssignedTransactionId() here,
1165  * because we've just added xids to the known assigned xids machinery that
1166  * haven't gone through RecordKnownAssignedTransactionId().
1167  */
1171  {
1174  }
1175  TransactionIdRetreat(latestObservedXid); /* = running->nextXid - 1 */
1176 
1177  /* ----------
1178  * Now we've got the running xids we need to set the global values that
1179  * are used to track snapshots as they evolve further.
1180  *
1181  * - latestCompletedXid which will be the xmax for snapshots
1182  * - lastOverflowedXid which shows whether snapshots overflow
1183  * - nextXid
1184  *
1185  * If the snapshot overflowed, then we still initialise with what we know,
1186  * but the recovery snapshot isn't fully valid yet because we know there
1187  * are some subxids missing. We don't know the specific subxids that are
1188  * missing, so conservatively assume the last one is latestObservedXid.
1189  * ----------
1190  */
1191  if (running->subxid_overflow)
1192  {
1194 
1197  }
1198  else
1199  {
1201 
1203  }
1204 
1205  /*
1206  * If a transaction wrote a commit record in the gap between taking and
1207  * logging the snapshot then latestCompletedXid may already be higher than
1208  * the value from the snapshot, so check before we use the incoming value.
1209  * It also might not yet be set at all.
1210  */
1212 
1213  LWLockRelease(ProcArrayLock);
1214 
1215  /* ShmemVariableCache->nextXid must be beyond any observed xid. */
1217 
1219 
1222  elog(trace_recovery(DEBUG1), "recovery snapshots are now enabled");
1223  else
1225  "recovery snapshot waiting for non-overflowed snapshot or "
1226  "until oldest active xid on standby is at least %u (now %u)",
1228  running->oldestRunningXid);
1229 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId latestObservedXid
Definition: procarray.c:259
TransactionId oldestRunningXid
Definition: standby.h:80
#define DEBUG1
Definition: elog.h:25
static void KnownAssignedXidsDisplay(int trace_level)
Definition: procarray.c:4997
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:575
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:277
#define DEBUG3
Definition: elog.h:23
#define FullTransactionIdIsValid(x)
Definition: transam.h:55
static void MaintainLatestCompletedXidRecovery(TransactionId latestXid)
Definition: procarray.c:935
TransactionId * xids
Definition: standby.h:83
bool TransactionIdDidCommit(TransactionId transactionId)
Definition: transam.c:125
#define TransactionIdRetreat(dest)
Definition: transam.h:141
FullTransactionId nextXid
Definition: transam.h:213
int trace_recovery(int trace_level)
Definition: elog.c:3602
TransactionId latestCompletedXid
Definition: standby.h:81
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:308
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
static void KnownAssignedXidsReset(void)
Definition: procarray.c:5035
int numKnownAssignedXids
Definition: procarray.c:81
TransactionId lastOverflowedXid
Definition: procarray.c:93
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4540
TransactionId nextXid
Definition: standby.h:79
void * palloc(Size size)
Definition: mcxt.c:950
#define elog(elevel,...)
Definition: elog.h:228
int i
void ExpireOldKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4375
#define qsort(a, b, c, d)
Definition: port.h:503
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
static TransactionId standbySnapshotPendingXmin
Definition: procarray.c:266
HotStandbyState standbyState
Definition: xlog.c:209
void StandbyReleaseOldLocks(TransactionId oldxid)
Definition: standby.c:1005
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:136

◆ ProcArrayApplyXidAssignment()

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

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

1238 {
1239  TransactionId max_xid;
1240  int i;
1241 
1243 
1244  max_xid = TransactionIdLatest(topxid, nsubxids, subxids);
1245 
1246  /*
1247  * Mark all the subtransactions as observed.
1248  *
1249  * NOTE: This will fail if the subxid contains too many previously
1250  * unobserved xids to fit into known-assigned-xids. That shouldn't happen
1251  * as the code stands, because xid-assignment records should never contain
1252  * more than PGPROC_MAX_CACHED_SUBXIDS entries.
1253  */
1255 
1256  /*
1257  * Notice that we update pg_subtrans with the top-level xid, rather than
1258  * the parent xid. This is a difference between normal processing and
1259  * recovery, yet is still correct in all cases. The reason is that
1260  * subtransaction commit is not marked in clog until commit processing, so
1261  * all aborted subtransactions have already been clearly marked in clog.
1262  * As a result we are able to refer directly to the top-level
1263  * transaction's state rather than skipping through all the intermediate
1264  * states in the subtransaction tree. This should be the first time we
1265  * have attempted to SubTransSetParent().
1266  */
1267  for (i = 0; i < nsubxids; i++)
1268  SubTransSetParent(subxids[i], topxid);
1269 
1270  /* KnownAssignedXids isn't maintained yet, so we're done for now */
1272  return;
1273 
1274  /*
1275  * Uses same locking as transaction commit
1276  */
1277  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
1278 
1279  /*
1280  * Remove subxids from known-assigned-xacts.
1281  */
1283 
1284  /*
1285  * Advance lastOverflowedXid to be at least the last of these subxids.
1286  */
1288  procArray->lastOverflowedXid = max_xid;
1289 
1290  LWLockRelease(ProcArrayLock);
1291 }
uint32 TransactionId
Definition: c.h:575
TransactionId TransactionIdLatest(TransactionId mainxid, int nxids, const TransactionId *xids)
Definition: transam.c:365
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define InvalidTransactionId
Definition: transam.h:31
TransactionId lastOverflowedXid
Definition: procarray.c:93
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static void KnownAssignedXidsRemoveTree(TransactionId xid, int nsubxids, TransactionId *subxids)
Definition: procarray.c:4790
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
int i
void RecordKnownAssignedTransactionIds(TransactionId xid)
Definition: procarray.c:4266
void SubTransSetParent(TransactionId xid, TransactionId parent)
Definition: subtrans.c:74
HotStandbyState standbyState
Definition: xlog.c:209

◆ ProcArrayClearTransaction()

void ProcArrayClearTransaction ( PGPROC proc)

Definition at line 853 of file procarray.c.

References Assert, XidCacheStatus::count, PGPROC::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcGlobal, PGPROC::recoveryConflictPending, ShmemVariableCache, PGPROC::statusFlags, PROC_HDR::subxidStates, PGPROC::subxidStatus, VariableCacheData::xactCompletionCount, PGPROC::xid, PROC_HDR::xids, and PGPROC::xmin.

Referenced by PrepareTransaction().

854 {
855  size_t pgxactoff;
856 
857  /*
858  * Currently we need to lock ProcArrayLock exclusively here, as we
859  * increment xactCompletionCount below. We also need it at least in shared
860  * mode for pgproc->pgxactoff to stay the same below.
861  *
862  * We could however, as this action does not actually change anyone's view
863  * of the set of running XIDs (our entry is duplicate with the gxact that
864  * has already been inserted into the ProcArray), lower the lock level to
865  * shared if we were to make xactCompletionCount an atomic variable. But
866  * that doesn't seem worth it currently, as a 2PC commit is heavyweight
867  * enough for this not to be the bottleneck. If it ever becomes a
868  * bottleneck it may also be worth considering to combine this with the
869  * subsequent ProcArrayRemove()
870  */
871  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
872 
873  pgxactoff = proc->pgxactoff;
874 
875  ProcGlobal->xids[pgxactoff] = InvalidTransactionId;
876  proc->xid = InvalidTransactionId;
877 
879  proc->xmin = InvalidTransactionId;
880  proc->recoveryConflictPending = false;
881 
883  Assert(!proc->delayChkpt);
884 
885  /*
886  * Need to increment completion count even though transaction hasn't
887  * really committed yet. The reason for that is that GetSnapshotData()
888  * omits the xid of the current transaction, thus without the increment we
889  * otherwise could end up reusing the snapshot later. Which would be bad,
890  * because it might not count the prepared transaction as running.
891  */
893 
894  /* Clear the subtransaction-XID cache too */
895  Assert(ProcGlobal->subxidStates[pgxactoff].count == proc->subxidStatus.count &&
897  if (proc->subxidStatus.count > 0 || proc->subxidStatus.overflowed)
898  {
899  ProcGlobal->subxidStates[pgxactoff].count = 0;
900  ProcGlobal->subxidStates[pgxactoff].overflowed = false;
901  proc->subxidStatus.count = 0;
902  proc->subxidStatus.overflowed = false;
903  }
904 
905  LWLockRelease(ProcArrayLock);
906 }
XidCacheStatus * subxidStates
Definition: proc.h:325
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 statusFlags
Definition: proc.h:187
XidCacheStatus subxidStatus
Definition: proc.h:208
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:65
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool delayChkpt
Definition: proc.h:185
TransactionId xmin
Definition: proc.h:138
bool recoveryConflictPending
Definition: proc.h:167
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define InvalidTransactionId
Definition: transam.h:31
TransactionId * xids
Definition: proc.h:319
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:133
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:148
LocalTransactionId lxid
Definition: proc.h:143

◆ ProcArrayEndTransaction()

void ProcArrayEndTransaction ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 620 of file procarray.c.

References Assert, XidCacheStatus::count, PGPROC::delayChkpt, InvalidLocalTransactionId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockHeldByMe(), LWLockRelease(), PGPROC::lxid, XidCacheStatus::overflowed, PGPROC::pgxactoff, PROC_VACUUM_STATE_MASK, ProcArrayEndTransactionInternal(), ProcArrayGroupClearXid(), ProcGlobal, PGPROC::recoveryConflictPending, PGPROC::statusFlags, PROC_HDR::statusFlags, PGPROC::subxidStatus, TransactionIdIsValid, PGPROC::xid, and PGPROC::xmin.

Referenced by AbortTransaction(), and CommitTransaction().

621 {
622  if (TransactionIdIsValid(latestXid))
623  {
624  /*
625  * We must lock ProcArrayLock while clearing our advertised XID, so
626  * that we do not exit the set of "running" transactions while someone
627  * else is taking a snapshot. See discussion in
628  * src/backend/access/transam/README.
629  */
631 
632  /*
633  * If we can immediately acquire ProcArrayLock, we clear our own XID
634  * and release the lock. If not, use group XID clearing to improve
635  * efficiency.
636  */
637  if (LWLockConditionalAcquire(ProcArrayLock, LW_EXCLUSIVE))
638  {
639  ProcArrayEndTransactionInternal(proc, latestXid);
640  LWLockRelease(ProcArrayLock);
641  }
642  else
643  ProcArrayGroupClearXid(proc, latestXid);
644  }
645  else
646  {
647  /*
648  * If we have no XID, we don't need to lock, since we won't affect
649  * anyone else's calculation of a snapshot. We might change their
650  * estimate of global xmin, but that's OK.
651  */
653  Assert(proc->subxidStatus.count == 0);
655 
657  proc->xmin = InvalidTransactionId;
658  proc->delayChkpt = false; /* be sure this is cleared in abort */
659  proc->recoveryConflictPending = false;
660 
661  /* must be cleared with xid/xmin: */
662  /* avoid unnecessarily dirtying shared cachelines */
664  {
665  Assert(!LWLockHeldByMe(ProcArrayLock));
666  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
670  LWLockRelease(ProcArrayLock);
671  }
672  }
673 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1926
static void ProcArrayEndTransactionInternal(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:681
static void ProcArrayGroupClearXid(PGPROC *proc, TransactionId latestXid)
Definition: procarray.c:739
PROC_HDR * ProcGlobal
Definition: proc.c:80
uint8 statusFlags
Definition: proc.h:187
XidCacheStatus subxidStatus
Definition: proc.h:208
#define PROC_VACUUM_STATE_MASK
Definition: proc.h:65
bool overflowed
Definition: proc.h:43
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool delayChkpt
Definition: proc.h:185
TransactionId xmin
Definition: proc.h:138
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1378
bool recoveryConflictPending
Definition: proc.h:167
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:133
#define InvalidLocalTransactionId
Definition: lock.h:68
int pgxactoff
Definition: proc.h:148
uint8 * statusFlags
Definition: proc.h:331
#define TransactionIdIsValid(xid)
Definition: transam.h:41
LocalTransactionId lxid
Definition: proc.h:143

◆ ProcArrayGetReplicationSlotXmin()

void ProcArrayGetReplicationSlotXmin ( TransactionId xmin,
TransactionId catalog_xmin 
)

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

3795 {
3796  LWLockAcquire(ProcArrayLock, LW_SHARED);
3797 
3798  if (xmin != NULL)
3800 
3801  if (catalog_xmin != NULL)
3802  *catalog_xmin = procArray->replication_slot_catalog_xmin;
3803 
3804  LWLockRelease(ProcArrayLock);
3805 }
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206

◆ ProcArrayInitRecovery()

void ProcArrayInitRecovery ( TransactionId  initializedUptoXID)

Definition at line 969 of file procarray.c.

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

Referenced by StartupXLOG().

970 {
972  Assert(TransactionIdIsNormal(initializedUptoXID));
973 
974  /*
975  * we set latestObservedXid to the xid SUBTRANS has been initialized up
976  * to, so we can extend it from that point onwards in
977  * RecordKnownAssignedTransactionIds, and when we get consistent in
978  * ProcArrayApplyRecoveryInfo().
979  */
980  latestObservedXid = initializedUptoXID;
982 }
static TransactionId latestObservedXid
Definition: procarray.c:259
#define TransactionIdRetreat(dest)
Definition: transam.h:141
#define Assert(condition)
Definition: c.h:792
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
HotStandbyState standbyState
Definition: xlog.c:209

◆ ProcArrayInstallImportedXmin()

bool ProcArrayInstallImportedXmin ( TransactionId  xmin,
VirtualTransactionId sourcevxid 
)

Definition at line 2472 of file procarray.c.

References Assert, VirtualTransactionId::backendId, PGPROC::backendId, PGPROC::databaseId, VirtualTransactionId::localTransactionId, LW_SHARED, LWLockAcquire(), LWLockRelease(), PGPROC::lxid, MyDatabaseId, MyProc, ProcArrayStruct::numProcs, ProcArrayStruct::pgprocnos, PROC_IN_VACUUM, procArray, ProcGlobal, PROC_HDR::statusFlags, TransactionIdIsNormal, TransactionIdPrecedesOrEquals(), TransactionXmin, UINT32_ACCESS_ONCE, and PGPROC::xmin.

Referenced by GetSerializableTransactionSnapshotInt(), and SetTransactionSnapshot().

2474 {
2475  bool result = false;
2476  ProcArrayStruct *arrayP = procArray;
2477  int index;
2478 
2480  if (!sourcevxid)
2481  return false;
2482 
2483  /* Get lock so source xact can't end while we're doing this */
2484  LWLockAcquire(ProcArrayLock, LW_SHARED);
2485 
2486  for (index = 0; index < arrayP->numProcs; index++)
2487  {
2488  int pgprocno = arrayP->pgprocnos[index];
2489  PGPROC *proc = &allProcs[pgprocno];
2490  int statusFlags = ProcGlobal->statusFlags[index];
2491  TransactionId xid;
2492 
2493  /* Ignore procs running LAZY VACUUM */
2494  if (statusFlags & PROC_IN_VACUUM)
2495  continue;
2496 
2497  /* We are only interested in the specific virtual transaction. */
2498  if (proc->backendId != sourcevxid->backendId)
2499  continue;
2500  if (proc->lxid != sourcevxid->localTransactionId)
2501  continue;
2502 
2503  /*
2504  * We check the transaction's database ID for paranoia's sake: if it's
2505  * in another DB then its xmin does not cover us. Caller should have
2506  * detected this already, so we just treat any funny cases as
2507  * "transaction not found".
2508  */
2509  if (proc->databaseId != MyDatabaseId)
2510  continue;
2511 
2512  /*
2513  * Likewise, let's just make real sure its xmin does cover us.
2514  */
2515  xid = UINT32_ACCESS_ONCE(proc->xmin);
2516  if (!TransactionIdIsNormal(xid) ||
2517  !TransactionIdPrecedesOrEquals(xid, xmin))
2518  continue;
2519 
2520  /*
2521  * We're good. Install the new xmin. As in GetSnapshotData, set
2522  * TransactionXmin too. (Note that because snapmgr.c called
2523  * GetSnapshotData first, we'll be overwriting a valid xmin here, so
2524  * we don't check that.)
2525  */
2526  MyProc->xmin = TransactionXmin = xmin;
2527 
2528  result = true;
2529  break;
2530  }
2531 
2532  LWLockRelease(ProcArrayLock);
2533 
2534  return result;
2535 }
BackendId backendId
Definition: proc.h:153
uint32 TransactionId
Definition: c.h:575
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
PROC_HDR * ProcGlobal
Definition: proc.c:80
LocalTransactionId localTransactionId
Definition: lock.h:65
TransactionId TransactionXmin
Definition: snapmgr.c:112
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define PROC_IN_VACUUM
Definition: proc.h:55
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
static ProcArrayStruct * procArray
Definition: procarray.c:250
Oid MyDatabaseId
Definition: globals.c:86
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:792
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
uint8 * statusFlags
Definition: proc.h:331
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
Definition: proc.h:121
LocalTransactionId lxid
Definition: proc.h:143

◆ ProcArrayInstallRestoredXmin()

bool ProcArrayInstallRestoredXmin ( TransactionId  xmin,
PGPROC proc 
)

Definition at line 2547 of file procarray.c.

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

Referenced by SetTransactionSnapshot().

2548 {
2549  bool result = false;
2550  TransactionId xid;
2551 
2553  Assert(proc != NULL);
2554 
2555  /* Get lock so source xact can't end while we're doing this */
2556  LWLockAcquire(ProcArrayLock, LW_SHARED);
2557 
2558  /*
2559  * Be certain that the referenced PGPROC has an advertised xmin which is
2560  * no later than the one we're installing, so that the system-wide xmin
2561  * can't go backwards. Also, make sure it's running in the same database,
2562  * so that the per-database xmin cannot go backwards.
2563  */
2564  xid = UINT32_ACCESS_ONCE(proc->xmin);
2565  if (proc->databaseId == MyDatabaseId &&
2566  TransactionIdIsNormal(xid) &&
2567  TransactionIdPrecedesOrEquals(xid, xmin))
2568  {
2569  MyProc->xmin = TransactionXmin = xmin;
2570  result = true;
2571  }
2572 
2573  LWLockRelease(ProcArrayLock);
2574 
2575  return result;
2576 }
uint32 TransactionId
Definition: c.h:575
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId TransactionXmin
Definition: snapmgr.c:112
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
TransactionId xmin
Definition: proc.h:138
Oid databaseId
Definition: proc.h:154
Oid MyDatabaseId
Definition: globals.c:86
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

◆ ProcArrayRemove()

void ProcArrayRemove ( PGPROC proc,
TransactionId  latestXid 
)

Definition at line 525 of file procarray.c.

References PROC_HDR::allProcs, Assert, XidCacheStatus::count, elog, LOG, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), ProcArrayStruct::numProcs, XidCacheStatus::overflowed, PGPROC::pgprocno, ProcArrayStruct::pgprocnos, PGPROC::pgxactoff, PGPROC::pid, procArray, ProcGlobal, ShmemVariableCache, PROC_HDR::statusFlags, PROC_HDR::subxidStates, TransactionIdIsValid, VariableCacheData::xactCompletionCount, and PROC_HDR::xids.

Referenced by FinishPreparedTransaction(), and RemoveProcFromArray().

526 {
527  ProcArrayStruct *arrayP = procArray;
528  int index;
529 
530 #ifdef XIDCACHE_DEBUG
531  /* dump stats at backend shutdown, but not prepared-xact end */
532  if (proc->pid != 0)
533  DisplayXidCache();
534 #endif
535 
536  /* See ProcGlobal comment explaining why both locks are held */
537  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
538  LWLockAcquire(XidGenLock, LW_EXCLUSIVE);
539 
540  Assert(ProcGlobal->allProcs[arrayP->pgprocnos[proc->pgxactoff]].pgxactoff == proc->pgxactoff);
541 
542  if (TransactionIdIsValid(latestXid))
543  {
545 
546  /* Advance global latestCompletedXid while holding the lock */
547  MaintainLatestCompletedXid(latestXid);
548 
549  /* Same with xactCompletionCount */
551 
552  ProcGlobal->xids[proc->pgxactoff] = 0;
555  }
556  else
557  {
558  /* Shouldn't be trying to remove a live transaction here */
560  }
561 
565  ProcGlobal->statusFlags[proc->pgxactoff] = 0;
566 
567  for (index = 0; index < arrayP->numProcs; index++)
568  {
569  if (arrayP->pgprocnos[index] == proc->pgprocno)
570  {
571  /* Keep the PGPROC array sorted. See notes above */
572  memmove(&arrayP->pgprocnos[index], &arrayP->pgprocnos[index + 1],
573  (arrayP->numProcs - index - 1) * sizeof(*arrayP->pgprocnos));
574  memmove(&ProcGlobal->xids[index], &ProcGlobal->xids[index + 1],
575  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->xids));
576  memmove(&ProcGlobal->subxidStates[index], &ProcGlobal->subxidStates[index + 1],
577  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->subxidStates));
578  memmove(&ProcGlobal->statusFlags[index], &ProcGlobal->statusFlags[index + 1],
579  (arrayP->numProcs - index - 1) * sizeof(*ProcGlobal->statusFlags));
580 
581  arrayP->pgprocnos[arrayP->numProcs - 1] = -1; /* for debugging */
582  arrayP->numProcs--;
583 
584  /* adjust for removed PGPROC */
585  for (; index < arrayP->numProcs; index++)
586  allProcs[arrayP->pgprocnos[index]].pgxactoff--;
587 
588  /*
589  * Release in reversed acquisition order, to reduce frequency of
590  * having to wait for XidGenLock while holding ProcArrayLock.
591  */
592  LWLockRelease(XidGenLock);
593  LWLockRelease(ProcArrayLock);
594  return;
595  }
596  }
597 
598  /* Oops */
599  LWLockRelease(XidGenLock);
600  LWLockRelease(ProcArrayLock);
601 
602  elog(LOG, "failed to find proc %p in ProcArray", proc);
603 }
XidCacheStatus * subxidStates
Definition: proc.h:325
uint64 xactCompletionCount
Definition: transam.h:241
PROC_HDR * ProcGlobal
Definition: proc.c:80
#define LOG
Definition: elog.h:26
bool overflowed
Definition: proc.h:43
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:913
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
uint8 count
Definition: proc.h:41
int pgprocno
Definition: proc.h:150
#define elog(elevel,...)
Definition: elog.h:228
int pgxactoff
Definition: proc.h:148
PGPROC * allProcs
Definition: proc.h:316
uint8 * statusFlags
Definition: proc.h:331
#define TransactionIdIsValid(xid)
Definition: transam.h:41
int pid
Definition: proc.h:146

◆ ProcArraySetReplicationSlotXmin()

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

Definition at line 3771 of file procarray.c.

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

Referenced by ReplicationSlotsComputeRequiredXmin().

3773 {
3774  Assert(!already_locked || LWLockHeldByMe(ProcArrayLock));
3775 
3776  if (!already_locked)
3777  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3778 
3780  procArray->replication_slot_catalog_xmin = catalog_xmin;
3781 
3782  if (!already_locked)
3783  LWLockRelease(ProcArrayLock);
3784 }
bool LWLockHeldByMe(LWLock *l)
Definition: lwlock.c:1926
TransactionId replication_slot_catalog_xmin
Definition: procarray.c:98
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
static ProcArrayStruct * procArray
Definition: procarray.c:250
TransactionId replication_slot_xmin
Definition: procarray.c:96
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206

◆ ProcArrayShmemSize()

Size ProcArrayShmemSize ( void  )

Definition at line 352 of file procarray.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

353 {
354  Size size;
355 
356  /* Size of the ProcArray structure itself */
357 #define PROCARRAY_MAXPROCS (MaxBackends + max_prepared_xacts)
358 
359  size = offsetof(ProcArrayStruct, pgprocnos);
360  size = add_size(size, mul_size(sizeof(int), PROCARRAY_MAXPROCS));
361 
362  /*
363  * During Hot Standby processing we have a data structure called
364  * KnownAssignedXids, created in shared memory. Local data structures are
365  * also created in various backends during GetSnapshotData(),
366  * TransactionIdIsInProgress() and GetRunningTransactionData(). All of the
367  * main structures created in those functions must be identically sized,
368  * since we may at times copy the whole of the data structures around. We
369  * refer to this size as TOTAL_MAX_CACHED_SUBXIDS.
370  *
371  * Ideally we'd only create this structure if we were actually doing hot
372  * standby in the current run, but we don't know that yet at the time
373  * shared memory is being set up.
374  */
375 #define TOTAL_MAX_CACHED_SUBXIDS \
376  ((PGPROC_MAX_CACHED_SUBXIDS + 1) * PROCARRAY_MAXPROCS)
377 
378  if (EnableHotStandby)
379  {
380  size = add_size(size,
381  mul_size(sizeof(TransactionId),
383  size = add_size(size,
384  mul_size(sizeof(bool), TOTAL_MAX_CACHED_SUBXIDS));
385  }
386 
387  return size;
388 }
#define PROCARRAY_MAXPROCS
uint32 TransactionId
Definition: c.h:575
Size mul_size(Size s1, Size s2)
Definition: shmem.c:519
Size add_size(Size s1, Size s2)
Definition: shmem.c:502
#define TOTAL_MAX_CACHED_SUBXIDS
size_t Size
Definition: c.h:528
bool EnableHotStandby
Definition: xlog.c:98
#define offsetof(type, field)
Definition: c.h:715

◆ RecordKnownAssignedTransactionIds()

void RecordKnownAssignedTransactionIds ( TransactionId  xid)

Definition at line 4266 of file procarray.c.

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

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

4267 {
4271 
4272  elog(trace_recovery(DEBUG4), "record known xact %u latestObservedXid %u",
4273  xid, latestObservedXid);
4274 
4275  /*
4276  * When a newly observed xid arrives, it is frequently the case that it is
4277  * *not* the next xid in sequence. When this occurs, we must treat the
4278  * intervening xids as running also.
4279  */
4281  {
4282  TransactionId next_expected_xid;
4283 
4284  /*
4285  * Extend subtrans like we do in GetNewTransactionId() during normal
4286  * operation using individual extend steps. Note that we do not need
4287  * to extend clog since its extensions are WAL logged.
4288  *
4289  * This part has to be done regardless of standbyState since we
4290  * immediately start assigning subtransactions to their toplevel
4291  * transactions.
4292  */
4293  next_expected_xid = latestObservedXid;
4294  while (TransactionIdPrecedes(next_expected_xid, xid))
4295  {
4296  TransactionIdAdvance(next_expected_xid);
4297  ExtendSUBTRANS(next_expected_xid);
4298  }
4299  Assert(next_expected_xid == xid);
4300 
4301  /*
4302  * If the KnownAssignedXids machinery isn't up yet, there's nothing
4303  * more to do since we don't track assigned xids yet.
4304  */
4306  {
4307  latestObservedXid = xid;
4308  return;
4309  }
4310 
4311  /*
4312  * Add (latestObservedXid, xid] onto the KnownAssignedXids array.
4313  */
4314  next_expected_xid = latestObservedXid;
4315  TransactionIdAdvance(next_expected_xid);
4316  KnownAssignedXidsAdd(next_expected_xid, xid, false);
4317 
4318  /*
4319  * Now we can advance latestObservedXid
4320  */
4321  latestObservedXid = xid;
4322 
4323  /* ShmemVariableCache->nextXid must be beyond any observed xid */
4325  next_expected_xid = latestObservedXid;
4326  TransactionIdAdvance(next_expected_xid);
4327  }
4328 }
#define TransactionIdAdvance(dest)
Definition: transam.h:91
static TransactionId latestObservedXid
Definition: procarray.c:259
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:334
uint32 TransactionId
Definition: c.h:575
void AdvanceNextFullTransactionIdPastXid(TransactionId xid)
Definition: varsup.c:277
#define DEBUG4
Definition: elog.h:22
int trace_recovery(int trace_level)
Definition: elog.c:3602
void ExtendSUBTRANS(TransactionId newestXact)
Definition: subtrans.c:308
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define Assert(condition)
Definition: c.h:792
static void KnownAssignedXidsAdd(TransactionId from_xid, TransactionId to_xid, bool exclusive_lock)
Definition: procarray.c:4540
#define elog(elevel,...)
Definition: elog.h:228
#define TransactionIdIsValid(xid)
Definition: transam.h:41
HotStandbyState standbyState
Definition: xlog.c:209

◆ SignalVirtualTransaction()

pid_t SignalVirtualTransaction ( VirtualTransactionId  vxid,
ProcSignalReason  sigmode,
bool  conflictPending 
)

Definition at line 3332 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 CancelVirtualTransaction(), and ResolveRecoveryConflictWithLock().

3334 {
3335  ProcArrayStruct *arrayP = procArray;
3336  int index;
3337  pid_t pid = 0;
3338 
3339  LWLockAcquire(ProcArrayLock, LW_SHARED);
3340 
3341  for (index = 0; index < arrayP->numProcs; index++)
3342  {
3343  int pgprocno = arrayP->pgprocnos[index];
3344  PGPROC *proc = &allProcs[pgprocno];
3345  VirtualTransactionId procvxid;
3346 
3347  GET_VXID_FROM_PGPROC(procvxid, *proc);
3348 
3349  if (procvxid.backendId == vxid.backendId &&
3350  procvxid.localTransactionId == vxid.localTransactionId)
3351  {
3352  proc->recoveryConflictPending = conflictPending;
3353  pid = proc->pid;
3354  if (pid != 0)
3355  {
3356  /*
3357  * Kill the pid if it's still here. If not, that's what we
3358  * wanted so ignore any errors.
3359  */
3360  (void) SendProcSignal(pid, sigmode, vxid.backendId);
3361  }
3362  break;
3363  }
3364  }
3365 
3366  LWLockRelease(ProcArrayLock);
3367 
3368  return pid;
3369 }
#define GET_VXID_FROM_PGPROC(vxid, proc)
Definition: lock.h:79
LocalTransactionId localTransactionId
Definition: lock.h:65
Definition: type.h:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:256
bool recoveryConflictPending
Definition: proc.h:167
static PGPROC * allProcs
Definition: procarray.c:252
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
BackendId backendId
Definition: lock.h:64
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ TerminateOtherDBBackends()

void TerminateOtherDBBackends ( Oid  databaseId)

Definition at line 3663 of file procarray.c.

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

Referenced by dropdb().

3664 {
3665  ProcArrayStruct *arrayP = procArray;
3666  List *pids = NIL;
3667  int nprepared = 0;
3668  int i;
3669 
3670  LWLockAcquire(ProcArrayLock, LW_SHARED);
3671 
3672  for (i = 0; i < procArray->numProcs; i++)
3673  {
3674  int pgprocno = arrayP->pgprocnos[i];
3675  PGPROC *proc = &allProcs[pgprocno];
3676 
3677  if (proc->databaseId != databaseId)
3678  continue;
3679  if (proc == MyProc)
3680  continue;
3681 
3682  if (proc->pid != 0)
3683  pids = lappend_int(pids, proc->pid);
3684  else
3685  nprepared++;
3686  }
3687 
3688  LWLockRelease(ProcArrayLock);
3689 
3690  if (nprepared > 0)
3691  ereport(ERROR,
3692  (errcode(ERRCODE_OBJECT_IN_USE),
3693  errmsg("database \"%s\" is being used by prepared transactions",
3694  get_database_name(databaseId)),
3695  errdetail_plural("There is %d prepared transaction using the database.",
3696  "There are %d prepared transactions using the database.",
3697  nprepared,
3698  nprepared)));
3699 
3700  if (pids)
3701  {
3702  ListCell *lc;
3703 
3704  /*
3705  * Check whether we have the necessary rights to terminate other
3706  * sessions. We don't terminate any session until we ensure that we
3707  * have rights on all the sessions to be terminated. These checks are
3708  * the same as we do in pg_terminate_backend.
3709  *
3710  * In this case we don't raise some warnings - like "PID %d is not a
3711  * PostgreSQL server process", because for us already finished session
3712  * is not a problem.
3713  */
3714  foreach(lc, pids)
3715  {
3716  int pid = lfirst_int(lc);
3717  PGPROC *proc = BackendPidGetProc(pid);
3718 
3719  if (proc != NULL)
3720  {
3721  /* Only allow superusers to signal superuser-owned backends. */
3722  if (superuser_arg(proc->roleId) && !superuser())
3723  ereport(ERROR,
3724  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3725  errmsg("must be a superuser to terminate superuser process")));
3726 
3727  /* Users can signal backends they have role membership in. */
3728  if (!has_privs_of_role(GetUserId(), proc->roleId) &&
3729  !has_privs_of_role(GetUserId(), DEFAULT_ROLE_SIGNAL_BACKENDID))
3730  ereport(ERROR,
3731  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
3732  errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
3733  }
3734  }
3735 
3736  /*
3737  * There's a race condition here: once we release the ProcArrayLock,
3738  * it's possible for the session to exit before we issue kill. That
3739  * race condition possibility seems too unlikely to worry about. See
3740  * pg_signal_backend.
3741  */
3742  foreach(lc, pids)
3743  {
3744  int pid = lfirst_int(lc);
3745  PGPROC *proc = BackendPidGetProc(pid);
3746 
3747  if (proc != NULL)
3748  {
3749  /*
3750  * If we have setsid(), signal the backend's whole process
3751  * group
3752  */
3753 #ifdef HAVE_SETSID
3754  (void) kill(-pid, SIGTERM);
3755 #else
3756  (void) kill(pid, SIGTERM);
3757 #endif
3758  }
3759  }
3760  }
3761 }
#define NIL
Definition: pg_list.h:65
Oid GetUserId(void)
Definition: miscinit.c:476
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3036
PGPROC * MyProc
Definition: proc.c:68
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:4895
Oid roleId
Definition: proc.h:155
int errcode(int sqlerrcode)
Definition: elog.c:704
bool superuser(void)
Definition: superuser.c:46
#define kill(pid, sig)
Definition: win32_port.h:454
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define ERROR
Definition: elog.h:45
#define lfirst_int(lc)
Definition: pg_list.h:170
char * get_database_name(Oid dbid)
Definition: dbcommands.c:2155
static PGPROC * allProcs
Definition: procarray.c:252
Oid databaseId
Definition: proc.h:154
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
List * lappend_int(List *list, int datum)
Definition: list.c:339
static ProcArrayStruct * procArray
Definition: procarray.c:250
#define ereport(elevel,...)
Definition: elog.h:155
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
int errdetail_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1140
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
Definition: proc.h:121
Definition: pg_list.h:50
int pid
Definition: proc.h:146

◆ TransactionIdIsActive()

bool TransactionIdIsActive ( TransactionId  xid)

Definition at line 1552 of file procarray.c.

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

1553 {
1554  bool result = false;
1555  ProcArrayStruct *arrayP = procArray;
1556  TransactionId *other_xids = ProcGlobal->xids;
1557  int i;
1558 
1559  /*
1560  * Don't bother checking a transaction older than RecentXmin; it could not
1561  * possibly still be running.
1562  */
1564  return false;
1565 
1566  LWLockAcquire(ProcArrayLock, LW_SHARED);
1567 
1568  for (i = 0; i < arrayP->numProcs; i++)
1569  {
1570  int pgprocno = arrayP->pgprocnos[i];
1571  PGPROC *proc = &allProcs[pgprocno];
1572  TransactionId pxid;
1573 
1574  /* Fetch xid just once - see GetNewTransactionId */
1575  pxid = UINT32_ACCESS_ONCE(other_xids[i]);
1576 
1577  if (!TransactionIdIsValid(pxid))
1578  continue;
1579 
1580  if (proc->pid == 0)
1581  continue; /* ignore prepared transactions */
1582 
1583  if (TransactionIdEquals(pxid, xid))
1584  {
1585  result = true;
1586  break;
1587  }
1588  }
1589 
1590  LWLockRelease(ProcArrayLock);
1591 
1592  return result;
1593 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:575
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
TransactionId RecentXmin
Definition: snapmgr.c:113
PROC_HDR * ProcGlobal
Definition: proc.c:80
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121
int pid
Definition: proc.h:146

◆ TransactionIdIsInProgress()

bool TransactionIdIsInProgress ( TransactionId  xid)

Definition at line 1320 of file procarray.c.

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

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

1321 {
1322  static TransactionId *xids = NULL;
1323  static TransactionId *other_xids;
1324  XidCacheStatus *other_subxidstates;
1325  int nxids = 0;
1326  ProcArrayStruct *arrayP = procArray;
1327  TransactionId topxid;
1328  TransactionId latestCompletedXid;
1329  int mypgxactoff;
1330  size_t numProcs;
1331  int j;
1332 
1333  /*
1334  * Don't bother checking a transaction older than RecentXmin; it could not
1335  * possibly still be running. (Note: in particular, this guarantees that
1336  * we reject InvalidTransactionId, FrozenTransactionId, etc as not
1337  * running.)
1338  */
1340  {
1342  return false;
1343  }
1344 
1345  /*
1346  * We may have just checked the status of this transaction, so if it is
1347  * already known to be completed, we can fall out without any access to
1348  * shared memory.
1349  */
1351  {
1353  return false;
1354  }
1355 
1356  /*
1357  * Also, we can handle our own transaction (and subtransactions) without
1358  * any access to shared memory.
1359  */
1361  {
1363  return true;
1364  }
1365 
1366  /*
1367  * If first time through, get workspace to remember main XIDs in. We
1368  * malloc it permanently to avoid repeated palloc/pfree overhead.
1369  */
1370  if (xids == NULL)
1371  {
1372  /*
1373  * In hot standby mode, reserve enough space to hold all xids in the
1374  * known-assigned list. If we later finish recovery, we no longer need
1375  * the bigger array, but we don't bother to shrink it.
1376  */
1377  int maxxids = RecoveryInProgress() ? TOTAL_MAX_CACHED_SUBXIDS : arrayP->maxProcs;
1378 
1379  xids = (TransactionId *) malloc(maxxids * sizeof(TransactionId));
1380  if (xids == NULL)
1381  ereport(ERROR,
1382  (errcode(ERRCODE_OUT_OF_MEMORY),
1383  errmsg("out of memory")));
1384  }
1385 
1386  other_xids = ProcGlobal->xids;
1387  other_subxidstates = ProcGlobal->subxidStates;
1388 
1389  LWLockAcquire(ProcArrayLock, LW_SHARED);
1390 
1391  /*
1392  * Now that we have the lock, we can check latestCompletedXid; if the
1393  * target Xid is after that, it's surely still running.
1394  */
1395  latestCompletedXid =
1397  if (TransactionIdPrecedes(latestCompletedXid, xid))
1398  {
1399  LWLockRelease(ProcArrayLock);
1401  return true;
1402  }
1403 
1404  /* No shortcuts, gotta grovel through the array */
1405  mypgxactoff = MyProc->pgxactoff;
1406  numProcs = arrayP->numProcs;
1407  for (size_t pgxactoff = 0; pgxactoff < numProcs; pgxactoff++)
1408  {
1409  int pgprocno;
1410  PGPROC *proc;
1411  TransactionId pxid;
1412  int pxids;
1413 
1414  /* Ignore ourselves --- dealt with it above */
1415  if (pgxactoff == mypgxactoff)
1416  continue;
1417 
1418  /* Fetch xid just once - see GetNewTransactionId */
1419  pxid = UINT32_ACCESS_ONCE(other_xids[pgxactoff]);
1420 
1421  if (!TransactionIdIsValid(pxid))
1422  continue;
1423 
1424  /*
1425  * Step 1: check the main Xid
1426  */
1427  if (TransactionIdEquals(pxid, xid))
1428  {
1429  LWLockRelease(ProcArrayLock);
1431  return true;
1432  }
1433 
1434  /*
1435  * We can ignore main Xids that are younger than the target Xid, since
1436  * the target could not possibly be their child.
1437  */
1438  if (TransactionIdPrecedes(xid, pxid))
1439  continue;
1440 
1441  /*
1442  * Step 2: check the cached child-Xids arrays
1443  */
1444  pxids = other_subxidstates[pgxactoff].count;
1445  pg_read_barrier(); /* pairs with barrier in GetNewTransactionId() */
1446  pgprocno = arrayP->pgprocnos[pgxactoff];
1447  proc = &allProcs[pgprocno];
1448  for (j = pxids - 1; j >= 0; j--)
1449  {
1450  /* Fetch xid just once - see GetNewTransactionId */
1451  TransactionId cxid = UINT32_ACCESS_ONCE(proc->subxids.xids[j]);
1452 
1453  if (TransactionIdEquals(cxid, xid))
1454  {
1455  LWLockRelease(ProcArrayLock);
1457  return true;
1458  }
1459  }
1460 
1461  /*
1462  * Save the main Xid for step 4. We only need to remember main Xids
1463  * that have uncached children. (Note: there is no race condition
1464  * here because the overflowed flag cannot be cleared, only set, while
1465  * we hold ProcArrayLock. So we can't miss an Xid that we need to
1466  * worry about.)
1467  */
1468  if (other_subxidstates[pgxactoff].overflowed)
1469  xids[nxids++] = pxid;
1470  }
1471 
1472  /*
1473  * Step 3: in hot standby mode, check the known-assigned-xids list. XIDs
1474  * in the list must be treated as running.
1475  */
1476  if (RecoveryInProgress())
1477  {
1478  /* none of the PGPROC entries should have XIDs in hot standby mode */
1479  Assert(nxids == 0);
1480 
1481  if (KnownAssignedXidExists(xid))
1482  {
1483  LWLockRelease(ProcArrayLock);
1485  return true;
1486  }
1487 
1488  /*
1489  * If the KnownAssignedXids overflowed, we have to check pg_subtrans
1490  * too. Fetch all xids from KnownAssignedXids that are lower than
1491  * xid, since if xid is a subtransaction its parent will always have a
1492  * lower value. Note we will collect both main and subXIDs here, but
1493  * there's no help for it.
1494  */
1496  nxids = KnownAssignedXidsGet(xids, xid);
1497  }
1498 
1499  LWLockRelease(ProcArrayLock);
1500 
1501  /*
1502  * If none of the relevant caches overflowed, we know the Xid is not
1503  * running without even looking at pg_subtrans.
1504  */
1505  if (nxids == 0)
1506  {
1508  return false;
1509  }
1510 
1511  /*
1512  * Step 4: have to check pg_subtrans.
1513  *
1514  * At this point, we know it's either a subtransaction of one of the Xids
1515  * in xids[], or it's not running. If it's an already-failed
1516  * subtransaction, we want to say "not running" even though its parent may
1517  * still be running. So first, check pg_xact to see if it's been aborted.
1518  */
1520 
1521  if (TransactionIdDidAbort(xid))
1522  return false;
1523 
1524  /*
1525  * It isn't aborted, so check whether the transaction tree it belongs to
1526  * is still running (or, more precisely, whether it was running when we
1527  * held ProcArrayLock).
1528  */
1529  topxid = SubTransGetTopmostTransaction(xid);
1530  Assert(TransactionIdIsValid(topxid));
1531  if (!TransactionIdEquals(topxid, xid))
1532  {
1533  for (int i = 0; i < nxids; i++)
1534  {
1535  if (TransactionIdEquals(xids[i], topxid))
1536  return true;
1537  }
1538  }
1539 
1540  return false;
1541 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:575
bool TransactionIdIsCurrentTransactionId(TransactionId xid)
Definition: xact.c:869
TransactionId SubTransGetTopmostTransaction(TransactionId xid)
Definition: subtrans.c:150
XidCacheStatus * subxidStates
Definition: proc.h:325
PGPROC * MyProc
Definition: proc.c:68
#define UINT32_ACCESS_ONCE(var)
Definition: procarray.c:69
#define xc_by_my_xact_inc()
Definition: procarray.c:313
int errcode(int sqlerrcode)
Definition: elog.c:704
TransactionId RecentXmin
Definition: snapmgr.c:113
PROC_HDR * ProcGlobal
Definition: proc.c:80
FullTransactionId latestCompletedXid
Definition: transam.h:231
bool RecoveryInProgress(void)
Definition: xlog.c:8148
#define xc_by_child_xid_inc()
Definition: procarray.c:316
bool TransactionIdIsKnownCompleted(TransactionId transactionId)
Definition: transam.c:238
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define malloc(a)
Definition: header.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
#define xc_by_recent_xmin_inc()
Definition: procarray.c:311
#define xc_by_known_xact_inc()
Definition: procarray.c:312
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
#define ERROR
Definition: elog.h:45
#define xc_by_main_xid_inc()
Definition: procarray.c:315
#define xc_by_known_assigned_inc()
Definition: procarray.c:317
VariableCache ShmemVariableCache
Definition: varsup.c:34
TransactionId * xids
Definition: proc.h:319
static PGPROC * allProcs
Definition: procarray.c:252
struct XidCache subxids
Definition: proc.h:210
TransactionId lastOverflowedXid
Definition: procarray.c:93
bool TransactionIdDidAbort(TransactionId transactionId)
Definition: transam.c:181
#define xc_by_latest_xid_inc()
Definition: procarray.c:314
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
static ProcArrayStruct * procArray
Definition: procarray.c:250
static int KnownAssignedXidsGet(TransactionId *xarray, TransactionId xmax)
Definition: procarray.c:4890
#define ereport(elevel,...)
Definition: elog.h:155
int pgprocnos[FLEXIBLE_ARRAY_MEMBER]
Definition: procarray.c:101
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define TOTAL_MAX_CACHED_SUBXIDS
#define Assert(condition)
Definition: c.h:792
#define pg_read_barrier()
Definition: atomics.h:158
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
#define xc_no_overflow_inc()
Definition: procarray.c:318
uint8 count
Definition: proc.h:41
static bool KnownAssignedXidExists(TransactionId xid)
Definition: procarray.c:4751
#define xc_slow_answer_inc()
Definition: procarray.c:319
int errmsg(const char *fmt,...)
Definition: elog.c:915
int i
int pgxactoff
Definition: proc.h:148
#define TransactionIdIsValid(xid)
Definition: transam.h:41
Definition: proc.h:121

◆ XidCacheRemoveRunningXids()

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

Definition at line 3816 of file procarray.c.

References Assert, XidCacheStatus::count, elog, fprintf, i, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaintainLatestCompletedXid(), MyProc, pg_write_barrier, PGPROC::pgxactoff, ProcGlobal, PGPROC::subxids, PROC_HDR::subxidStates, PGPROC::subxidStatus, TransactionIdEquals, TransactionIdIsValid, WARNING, and XidCache::xids.

Referenced by RecordTransactionAbort().

3819 {
3820  int i,
3821  j;
3822  XidCacheStatus *mysubxidstat;
3823 
3825 
3826  /*
3827  * We must hold ProcArrayLock exclusively in order to remove transactions
3828  * from the PGPROC array. (See src/backend/access/transam/README.) It's
3829  * possible this could be relaxed since we know this routine is only used
3830  * to abort subtransactions, but pending closer analysis we'd best be
3831  * conservative.
3832  *
3833  * Note that we do not have to be careful about memory ordering of our own
3834  * reads wrt. GetNewTransactionId() here - only this process can modify
3835  * relevant fields of MyProc/ProcGlobal->xids[]. But we do have to be
3836  * careful about our own writes being well ordered.
3837  */
3838  LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
3839 
3840  mysubxidstat = &ProcGlobal->subxidStates[MyProc->pgxactoff];
3841 
3842  /*
3843  * Under normal circumstances xid and xids[] will be in increasing order,
3844  * as will be the entries in subxids. Scan backwards to avoid O(N^2)
3845  * behavior when removing a lot of xids.
3846  */
3847  for (i = nxids - 1; i >= 0; i--)
3848  {
3849  TransactionId anxid = xids[i];
3850 
3851  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3852  {
3853  if (TransactionIdEquals(MyProc->subxids.xids[j], anxid))
3854  {
3856  pg_write_barrier();
3857  mysubxidstat->count--;
3859  break;
3860  }
3861  }
3862 
3863  /*
3864  * Ordinarily we should have found it, unless the cache has
3865  * overflowed. However it's also possible for this routine to be
3866  * invoked multiple times for the same subtransaction, in case of an
3867  * error during AbortSubTransaction. So instead of Assert, emit a
3868  * debug warning.
3869  */
3870  if (j < 0 && !MyProc->subxidStatus.overflowed)
3871  elog(WARNING, "did not find subXID %u in MyProc", anxid);
3872  }
3873 
3874  for (j = MyProc->subxidStatus.count - 1; j >= 0; j--)
3875  {
3876  if (TransactionIdEquals(MyProc->subxids.xids[j], xid))
3877  {
3879  pg_write_barrier();
3880  mysubxidstat->count--;
3882  break;
3883  }
3884  }
3885  /* Ordinarily we should have found it, unless the cache has overflowed */
3886  if (j < 0 && !MyProc->subxidStatus.overflowed)
3887  elog(WARNING, "did not find subXID %u in MyProc", xid);
3888 
3889  /* Also advance global latestCompletedXid while holding the lock */
3890  MaintainLatestCompletedXid(latestXid);
3891 
3892  LWLockRelease(ProcArrayLock);
3893 }
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
uint32 TransactionId
Definition: c.h:575
XidCacheStatus * subxidStates
Definition: proc.h:325
PGPROC * MyProc
Definition: proc.c:68
PROC_HDR * ProcGlobal
Definition: proc.c:80
XidCacheStatus subxidStatus
Definition: proc.h:208
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1810
struct XidCache subxids
Definition: proc.h:210
#define WARNING
Definition: elog.h:40
static void MaintainLatestCompletedXid(TransactionId latestXid)
Definition: procarray.c:913
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define Assert(condition)
Definition: c.h:792
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1206
uint8 count
Definition: proc.h:41
#define elog(elevel,...)
Definition: elog.h:228
int i
int pgxactoff
Definition: proc.h:148
#define pg_write_barrier()
Definition: atomics.h:159
#define TransactionIdIsValid(xid)
Definition: transam.h:41