PostgreSQL Source Code  git master
clog.c File Reference
#include "postgres.h"
#include "access/clog.h"
#include "access/slru.h"
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "pgstat.h"
#include "storage/proc.h"
Include dependency graph for clog.c:

Go to the source code of this file.

Macros

#define CLOG_BITS_PER_XACT   2
 
#define CLOG_XACTS_PER_BYTE   4
 
#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)
 
#define CLOG_XACT_BITMASK   ((1 << CLOG_BITS_PER_XACT) - 1)
 
#define TransactionIdToPage(xid)   ((xid) / (TransactionId) CLOG_XACTS_PER_PAGE)
 
#define TransactionIdToPgIndex(xid)   ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)
 
#define TransactionIdToByte(xid)   (TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)
 
#define TransactionIdToBIndex(xid)   ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)
 
#define CLOG_XACTS_PER_LSN_GROUP   32 /* keep this a power of 2 */
 
#define CLOG_LSNS_PER_PAGE   (CLOG_XACTS_PER_PAGE / CLOG_XACTS_PER_LSN_GROUP)
 
#define GetLSNIndex(slotno, xid)
 
#define THRESHOLD_SUBTRANS_CLOG_OPT   5
 
#define XactCtl   (&XactCtlData)
 

Functions

static int ZeroCLOGPage (int pageno, bool writeXlog)
 
static bool CLOGPagePrecedes (int page1, int page2)
 
static void WriteZeroPageXlogRec (int pageno)
 
static void WriteTruncateXlogRec (int pageno, TransactionId oldestXact, Oid oldestXactDb)
 
static void TransactionIdSetPageStatus (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno, bool all_xact_same_page)
 
static void TransactionIdSetStatusBit (TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)
 
static void set_status_by_pages (int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
 
static bool TransactionGroupUpdateXidStatus (TransactionId xid, XidStatus status, XLogRecPtr lsn, int pageno)
 
static void TransactionIdSetPageStatusInternal (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
 
void TransactionIdSetTreeStatus (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
 
XidStatus TransactionIdGetStatus (TransactionId xid, XLogRecPtr *lsn)
 
Size CLOGShmemBuffers (void)
 
Size CLOGShmemSize (void)
 
void CLOGShmemInit (void)
 
void BootStrapCLOG (void)
 
void StartupCLOG (void)
 
void TrimCLOG (void)
 
void ShutdownCLOG (void)
 
void CheckPointCLOG (void)
 
void ExtendCLOG (TransactionId newestXact)
 
void TruncateCLOG (TransactionId oldestXact, Oid oldestxid_datoid)
 
void clog_redo (XLogReaderState *record)
 

Variables

static SlruCtlData XactCtlData
 

Macro Definition Documentation

◆ CLOG_BITS_PER_XACT

#define CLOG_BITS_PER_XACT   2

Definition at line 59 of file clog.c.

Referenced by TransactionIdGetStatus(), TransactionIdSetStatusBit(), and TrimCLOG().

◆ CLOG_LSNS_PER_PAGE

#define CLOG_LSNS_PER_PAGE   (CLOG_XACTS_PER_PAGE / CLOG_XACTS_PER_LSN_GROUP)

Definition at line 71 of file clog.c.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

◆ CLOG_XACT_BITMASK

#define CLOG_XACT_BITMASK   ((1 << CLOG_BITS_PER_XACT) - 1)

Definition at line 62 of file clog.c.

Referenced by TransactionIdGetStatus(), and TransactionIdSetStatusBit().

◆ CLOG_XACTS_PER_BYTE

#define CLOG_XACTS_PER_BYTE   4

Definition at line 60 of file clog.c.

◆ CLOG_XACTS_PER_LSN_GROUP

#define CLOG_XACTS_PER_LSN_GROUP   32 /* keep this a power of 2 */

Definition at line 70 of file clog.c.

◆ CLOG_XACTS_PER_PAGE

#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)

Definition at line 61 of file clog.c.

Referenced by CLOGPagePrecedes().

◆ GetLSNIndex

#define GetLSNIndex (   slotno,
  xid 
)
Value:
((slotno) * CLOG_LSNS_PER_PAGE + \
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:61
uint32 TransactionId
Definition: c.h:520
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:71
#define CLOG_XACTS_PER_LSN_GROUP
Definition: clog.c:70

Definition at line 73 of file clog.c.

Referenced by TransactionIdGetStatus(), and TransactionIdSetStatusBit().

◆ THRESHOLD_SUBTRANS_CLOG_OPT

#define THRESHOLD_SUBTRANS_CLOG_OPT   5

Definition at line 81 of file clog.c.

Referenced by TransactionGroupUpdateXidStatus(), and TransactionIdSetPageStatus().

◆ TransactionIdToBIndex

#define TransactionIdToBIndex (   xid)    ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)

Definition at line 67 of file clog.c.

Referenced by TransactionIdGetStatus(), TransactionIdSetStatusBit(), and TrimCLOG().

◆ TransactionIdToByte

#define TransactionIdToByte (   xid)    (TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)

Definition at line 66 of file clog.c.

Referenced by TransactionIdGetStatus(), TransactionIdSetStatusBit(), and TrimCLOG().

◆ TransactionIdToPage

◆ TransactionIdToPgIndex

#define TransactionIdToPgIndex (   xid)    ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE)

Definition at line 65 of file clog.c.

Referenced by ExtendCLOG(), and TrimCLOG().

◆ XactCtl

Function Documentation

◆ BootStrapCLOG()

void BootStrapCLOG ( void  )

Definition at line 704 of file clog.c.

References Assert, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SimpleLruWritePage(), XactCtl, and ZeroCLOGPage().

Referenced by BootStrapXLOG().

705 {
706  int slotno;
707 
708  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
709 
710  /* Create and zero the first page of the commit log */
711  slotno = ZeroCLOGPage(0, false);
712 
713  /* Make sure it's written out */
714  SimpleLruWritePage(XactCtl, slotno);
715  Assert(!XactCtl->shared->page_dirty[slotno]);
716 
717  LWLockRelease(XactSLRULock);
718 }
#define XactCtl
Definition: clog.c:88
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:597
#define Assert(condition)
Definition: c.h:745
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:730

◆ CheckPointCLOG()

void CheckPointCLOG ( void  )

Definition at line 834 of file clog.c.

References fsync_fname(), SimpleLruFlush(), and XactCtl.

Referenced by CheckPointGuts().

835 {
836  /* Flush dirty CLOG pages to disk */
837  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
838  SimpleLruFlush(XactCtl, true);
839 
840  /*
841  * fsync pg_xact to ensure that any files flushed previously are durably
842  * on disk.
843  */
844  fsync_fname("pg_xact", true);
845 
846  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
847 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:632
#define XactCtl
Definition: clog.c:88
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1128

◆ clog_redo()

void clog_redo ( XLogReaderState record)

Definition at line 995 of file clog.c.

References AdvanceOldestClogXid(), Assert, CLOG_TRUNCATE, CLOG_ZEROPAGE, elog, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), xl_clog_truncate::oldestXact, xl_clog_truncate::pageno, PANIC, SimpleLruTruncate(), SimpleLruWritePage(), XactCtl, XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, XLR_INFO_MASK, and ZeroCLOGPage().

996 {
997  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
998 
999  /* Backup blocks are not used in clog records */
1000  Assert(!XLogRecHasAnyBlockRefs(record));
1001 
1002  if (info == CLOG_ZEROPAGE)
1003  {
1004  int pageno;
1005  int slotno;
1006 
1007  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
1008 
1009  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
1010 
1011  slotno = ZeroCLOGPage(pageno, false);
1012  SimpleLruWritePage(XactCtl, slotno);
1013  Assert(!XactCtl->shared->page_dirty[slotno]);
1014 
1015  LWLockRelease(XactSLRULock);
1016  }
1017  else if (info == CLOG_TRUNCATE)
1018  {
1019  xl_clog_truncate xlrec;
1020 
1021  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
1022 
1023  /*
1024  * During XLOG replay, latest_page_number isn't set up yet; insert a
1025  * suitable value to bypass the sanity test in SimpleLruTruncate.
1026  */
1027  XactCtl->shared->latest_page_number = xlrec.pageno;
1028 
1030 
1032  }
1033  else
1034  elog(PANIC, "clog_redo: unknown op code %u", info);
1035 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1196
#define XactCtl
Definition: clog.c:88
unsigned char uint8
Definition: c.h:372
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define CLOG_ZEROPAGE
Definition: clog.h:54
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:597
int pageno
Definition: clog.h:33
#define CLOG_TRUNCATE
Definition: clog.h:55
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:305
TransactionId oldestXact
Definition: clog.h:34
#define Assert(condition)
Definition: c.h:745
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:730
#define elog(elevel,...)
Definition: elog.h:214
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:312

◆ CLOGPagePrecedes()

static bool CLOGPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 944 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

945 {
946  TransactionId xid1;
947  TransactionId xid2;
948 
949  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
950  xid1 += FirstNormalTransactionId;
951  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
952  xid2 += FirstNormalTransactionId;
953 
954  return TransactionIdPrecedes(xid1, xid2);
955 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:61
uint32 TransactionId
Definition: c.h:520
#define FirstNormalTransactionId
Definition: transam.h:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300

◆ CLOGShmemBuffers()

Size CLOGShmemBuffers ( void  )

Definition at line 675 of file clog.c.

References Max, Min, and NBuffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

676 {
677  return Min(128, Max(4, NBuffers / 512));
678 }
#define Min(x, y)
Definition: c.h:927
#define Max(x, y)
Definition: c.h:921
int NBuffers
Definition: globals.c:132

◆ CLOGShmemInit()

void CLOGShmemInit ( void  )

Definition at line 690 of file clog.c.

References CLOG_LSNS_PER_PAGE, CLOGPagePrecedes(), CLOGShmemBuffers(), LWTRANCHE_XACT_BUFFER, SimpleLruInit(), and XactCtl.

Referenced by CreateSharedMemoryAndSemaphores().

691 {
692  XactCtl->PagePrecedes = CLOGPagePrecedes;
694  XactSLRULock, "pg_xact", LWTRANCHE_XACT_BUFFER);
695 }
#define XactCtl
Definition: clog.c:88
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:71
static bool CLOGPagePrecedes(int page1, int page2)
Definition: clog.c:944
Size CLOGShmemBuffers(void)
Definition: clog.c:675
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
Definition: slru.c:175

◆ CLOGShmemSize()

Size CLOGShmemSize ( void  )

Definition at line 684 of file clog.c.

References CLOG_LSNS_PER_PAGE, CLOGShmemBuffers(), and SimpleLruShmemSize().

Referenced by CreateSharedMemoryAndSemaphores().

685 {
687 }
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:144
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:71
Size CLOGShmemBuffers(void)
Definition: clog.c:675

◆ ExtendCLOG()

void ExtendCLOG ( TransactionId  newestXact)

Definition at line 859 of file clog.c.

References FirstNormalTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TransactionIdEquals, TransactionIdToPage, TransactionIdToPgIndex, and ZeroCLOGPage().

Referenced by GetNewTransactionId().

860 {
861  int pageno;
862 
863  /*
864  * No work except at first XID of a page. But beware: just after
865  * wraparound, the first XID of page zero is FirstNormalTransactionId.
866  */
867  if (TransactionIdToPgIndex(newestXact) != 0 &&
869  return;
870 
871  pageno = TransactionIdToPage(newestXact);
872 
873  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
874 
875  /* Zero the page and make an XLOG entry about it */
876  ZeroCLOGPage(pageno, true);
877 
878  LWLockRelease(XactSLRULock);
879 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define TransactionIdToPgIndex(xid)
Definition: clog.c:65
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define FirstNormalTransactionId
Definition: transam.h:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:730

◆ set_status_by_pages()

static void set_status_by_pages ( int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn 
)
static

Definition at line 237 of file clog.c.

References Assert, i, InvalidTransactionId, TransactionIdSetPageStatus(), and TransactionIdToPage.

Referenced by TransactionIdSetTreeStatus().

239 {
240  int pageno = TransactionIdToPage(subxids[0]);
241  int offset = 0;
242  int i = 0;
243 
244  Assert(nsubxids > 0); /* else the pageno fetch above is unsafe */
245 
246  while (i < nsubxids)
247  {
248  int num_on_page = 0;
249  int nextpageno;
250 
251  do
252  {
253  nextpageno = TransactionIdToPage(subxids[i]);
254  if (nextpageno != pageno)
255  break;
256  num_on_page++;
257  i++;
258  } while (i < nsubxids);
259 
261  num_on_page, subxids + offset,
262  status, lsn, pageno, false);
263  offset = i;
264  pageno = nextpageno;
265  }
266 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
#define InvalidTransactionId
Definition: transam.h:31
#define Assert(condition)
Definition: c.h:745
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno, bool all_xact_same_page)
Definition: clog.c:273
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ ShutdownCLOG()

void ShutdownCLOG ( void  )

Definition at line 815 of file clog.c.

References fsync_fname(), SimpleLruFlush(), and XactCtl.

Referenced by ShutdownXLOG().

816 {
817  /* Flush dirty CLOG pages to disk */
818  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(false);
819  SimpleLruFlush(XactCtl, false);
820 
821  /*
822  * fsync pg_xact to ensure that any files flushed previously are durably
823  * on disk.
824  */
825  fsync_fname("pg_xact", true);
826 
827  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(false);
828 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:632
#define XactCtl
Definition: clog.c:88
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1128

◆ StartupCLOG()

void StartupCLOG ( void  )

Definition at line 747 of file clog.c.

References LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, ShmemVariableCache, TransactionIdToPage, XactCtl, and XidFromFullTransactionId.

Referenced by StartupXLOG().

748 {
750  int pageno = TransactionIdToPage(xid);
751 
752  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
753 
754  /*
755  * Initialize our idea of the latest page number.
756  */
757  XactCtl->shared->latest_page_number = pageno;
758 
759  LWLockRelease(XactSLRULock);
760 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
uint32 TransactionId
Definition: c.h:520
#define XactCtl
Definition: clog.c:88
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208

◆ TransactionGroupUpdateXidStatus()

static bool TransactionGroupUpdateXidStatus ( TransactionId  xid,
XidStatus  status,
XLogRecPtr  lsn,
int  pageno 
)
static

Definition at line 413 of file clog.c.

References PROC_HDR::allProcs, Assert, PROC_HDR::clogGroupFirst, PGPROC::clogGroupMember, PGPROC::clogGroupMemberLsn, PGPROC::clogGroupMemberPage, PGPROC::clogGroupMemberXid, PGPROC::clogGroupMemberXidStatus, PGPROC::clogGroupNext, XidCacheStatus::count, INVALID_PGPROCNO, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, pg_atomic_compare_exchange_u32(), pg_atomic_exchange_u32(), pg_atomic_read_u32(), pg_atomic_write_u32(), pg_write_barrier, PGPROC::pgprocno, PGSemaphoreLock(), PGSemaphoreUnlock(), pgstat_report_wait_end(), pgstat_report_wait_start(), ProcGlobal, PGPROC::sem, status(), PGPROC::subxids, PGPROC::subxidStatus, THRESHOLD_SUBTRANS_CLOG_OPT, TransactionIdIsValid, TransactionIdSetPageStatusInternal(), WAIT_EVENT_XACT_GROUP_UPDATE, and XidCache::xids.

Referenced by TransactionIdSetPageStatus().

415 {
416  volatile PROC_HDR *procglobal = ProcGlobal;
417  PGPROC *proc = MyProc;
418  uint32 nextidx;
419  uint32 wakeidx;
420 
421  /* We should definitely have an XID whose status needs to be updated. */
423 
424  /*
425  * Add ourselves to the list of processes needing a group XID status
426  * update.
427  */
428  proc->clogGroupMember = true;
429  proc->clogGroupMemberXid = xid;
431  proc->clogGroupMemberPage = pageno;
432  proc->clogGroupMemberLsn = lsn;
433 
434  nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst);
435 
436  while (true)
437  {
438  /*
439  * Add the proc to list, if the clog page where we need to update the
440  * current transaction status is same as group leader's clog page.
441  *
442  * There is a race condition here, which is that after doing the below
443  * check and before adding this proc's clog update to a group, the
444  * group leader might have already finished the group update for this
445  * page and becomes group leader of another group. This will lead to a
446  * situation where a single group can have different clog page
447  * updates. This isn't likely and will still work, just maybe a bit
448  * less efficiently.
449  */
450  if (nextidx != INVALID_PGPROCNO &&
452  {
453  proc->clogGroupMember = false;
454  return false;
455  }
456 
457  pg_atomic_write_u32(&proc->clogGroupNext, nextidx);
458 
460  &nextidx,
461  (uint32) proc->pgprocno))
462  break;
463  }
464 
465  /*
466  * If the list was not empty, the leader will update the status of our
467  * XID. It is impossible to have followers without a leader because the
468  * first process that has added itself to the list will always have
469  * nextidx as INVALID_PGPROCNO.
470  */
471  if (nextidx != INVALID_PGPROCNO)
472  {
473  int extraWaits = 0;
474 
475  /* Sleep until the leader updates our XID status. */
477  for (;;)
478  {
479  /* acts as a read barrier */
480  PGSemaphoreLock(proc->sem);
481  if (!proc->clogGroupMember)
482  break;
483  extraWaits++;
484  }
486 
488 
489  /* Fix semaphore count for any absorbed wakeups */
490  while (extraWaits-- > 0)
491  PGSemaphoreUnlock(proc->sem);
492  return true;
493  }
494 
495  /* We are the leader. Acquire the lock on behalf of everyone. */
496  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
497 
498  /*
499  * Now that we've got the lock, clear the list of processes waiting for
500  * group XID status update, saving a pointer to the head of the list.
501  * Trying to pop elements one at a time could lead to an ABA problem.
502  */
503  nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst,
505 
506  /* Remember head of list so we can perform wakeups after dropping lock. */
507  wakeidx = nextidx;
508 
509  /* Walk the list and update the status of all XIDs. */
510  while (nextidx != INVALID_PGPROCNO)
511  {
512  PGPROC *proc = &ProcGlobal->allProcs[nextidx];
513 
514  /*
515  * Transactions with more than THRESHOLD_SUBTRANS_CLOG_OPT sub-XIDs
516  * should not use group XID status update mechanism.
517  */
519 
521  proc->subxidStatus.count,
522  proc->subxids.xids,
524  proc->clogGroupMemberLsn,
525  proc->clogGroupMemberPage);
526 
527  /* Move to next proc in list. */
528  nextidx = pg_atomic_read_u32(&proc->clogGroupNext);
529  }
530 
531  /* We're done with the lock now. */
532  LWLockRelease(XactSLRULock);
533 
534  /*
535  * Now that we've released the lock, go back and wake everybody up. We
536  * don't do this under the lock so as to keep lock hold times to a
537  * minimum.
538  */
539  while (wakeidx != INVALID_PGPROCNO)
540  {
541  PGPROC *proc = &ProcGlobal->allProcs[wakeidx];
542 
543  wakeidx = pg_atomic_read_u32(&proc->clogGroupNext);
545 
546  /* ensure all previous writes are visible before follower continues. */
548 
549  proc->clogGroupMember = false;
550 
551  if (proc != MyProc)
552  PGSemaphoreUnlock(proc->sem);
553  }
554 
555  return true;
556 }
XidStatus clogGroupMemberXidStatus
Definition: proc.h:220
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:340
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:224
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:311
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:79
pg_atomic_uint32 clogGroupNext
Definition: proc.h:218
XidCacheStatus subxidStatus
Definition: proc.h:198
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:292
#define THRESHOLD_SUBTRANS_CLOG_OPT
Definition: clog.c:81
int clogGroupMemberPage
Definition: proc.h:222
TransactionId clogGroupMemberXid
Definition: proc.h:219
unsigned int uint32
Definition: c.h:374
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1381
struct XidCache subxids
Definition: proc.h:200
#define INVALID_PGPROCNO
Definition: proc.h:76
Definition: proc.h:303
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define Assert(condition)
Definition: c.h:745
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1357
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:320
uint8 count
Definition: proc.h:41
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:336
int pgprocno
Definition: proc.h:141
bool clogGroupMember
Definition: proc.h:217
#define pg_write_barrier()
Definition: atomics.h:159
static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:338
PGPROC * allProcs
Definition: proc.h:306
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:258
PGSemaphore sem
Definition: proc.h:118
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Definition: proc.h:112
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:241

◆ TransactionIdGetStatus()

XidStatus TransactionIdGetStatus ( TransactionId  xid,
XLogRecPtr lsn 
)

Definition at line 633 of file clog.c.

References CLOG_BITS_PER_XACT, CLOG_XACT_BITMASK, GetLSNIndex, LWLockRelease(), SimpleLruReadPage_ReadOnly(), status(), TransactionIdToBIndex, TransactionIdToByte, TransactionIdToPage, and XactCtl.

Referenced by TransactionIdGetCommitLSN(), and TransactionLogFetch().

634 {
635  int pageno = TransactionIdToPage(xid);
636  int byteno = TransactionIdToByte(xid);
637  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
638  int slotno;
639  int lsnindex;
640  char *byteptr;
642 
643  /* lock is acquired by SimpleLruReadPage_ReadOnly */
644 
645  slotno = SimpleLruReadPage_ReadOnly(XactCtl, pageno, xid);
646  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
647 
648  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
649 
650  lsnindex = GetLSNIndex(slotno, xid);
651  *lsn = XactCtl->shared->group_lsn[lsnindex];
652 
653  LWLockRelease(XactSLRULock);
654 
655  return status;
656 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:67
#define CLOG_XACT_BITMASK
Definition: clog.c:62
#define TransactionIdToPage(xid)
Definition: clog.c:64
#define GetLSNIndex(slotno, xid)
Definition: clog.c:73
#define XactCtl
Definition: clog.c:88
int XidStatus
Definition: clog.h:24
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define CLOG_BITS_PER_XACT
Definition: clog.c:59
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:482
#define TransactionIdToByte(xid)
Definition: clog.c:66
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ TransactionIdSetPageStatus()

static void TransactionIdSetPageStatus ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn,
int  pageno,
bool  all_xact_same_page 
)
static

Definition at line 273 of file clog.c.

References XidCacheStatus::count, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockRelease(), MyProc, PGPROC_MAX_CACHED_SUBXIDS, StaticAssertStmt, PGPROC::subxids, PGPROC::subxidStatus, THRESHOLD_SUBTRANS_CLOG_OPT, TransactionGroupUpdateXidStatus(), TransactionIdSetPageStatusInternal(), PGPROC::xid, and XidCache::xids.

Referenced by set_status_by_pages(), and TransactionIdSetTreeStatus().

277 {
278  /* Can't use group update when PGPROC overflows. */
280  "group clog threshold less than PGPROC cached subxids");
281 
282  /*
283  * When there is contention on XactSLRULock, we try to group multiple
284  * updates; a single leader process will perform transaction status
285  * updates for multiple backends so that the number of times XactSLRULock
286  * needs to be acquired is reduced.
287  *
288  * For this optimization to be safe, the XID and subxids in MyProc must be
289  * the same as the ones for which we're setting the status. Check that
290  * this is the case.
291  *
292  * For this optimization to be efficient, we shouldn't have too many
293  * sub-XIDs and all of the XIDs for which we're adjusting clog should be
294  * on the same page. Check those conditions, too.
295  */
296  if (all_xact_same_page && xid == MyProc->xid &&
297  nsubxids <= THRESHOLD_SUBTRANS_CLOG_OPT &&
298  nsubxids == MyProc->subxidStatus.count &&
299  memcmp(subxids, MyProc->subxids.xids,
300  nsubxids * sizeof(TransactionId)) == 0)
301  {
302  /*
303  * If we can immediately acquire XactSLRULock, we update the status of
304  * our own XID and release the lock. If not, try use group XID
305  * update. If that doesn't work out, fall back to waiting for the
306  * lock to perform an update for this transaction only.
307  */
308  if (LWLockConditionalAcquire(XactSLRULock, LW_EXCLUSIVE))
309  {
310  /* Got the lock without waiting! Do the update. */
311  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
312  lsn, pageno);
313  LWLockRelease(XactSLRULock);
314  return;
315  }
316  else if (TransactionGroupUpdateXidStatus(xid, status, lsn, pageno))
317  {
318  /* Group update mechanism has done the work. */
319  return;
320  }
321 
322  /* Fall through only if update isn't done yet. */
323  }
324 
325  /* Group update not applicable, or couldn't accept this page number. */
326  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
327  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
328  lsn, pageno);
329  LWLockRelease(XactSLRULock);
330 }
uint32 TransactionId
Definition: c.h:520
static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:413
PGPROC * MyProc
Definition: proc.c:67
XidCacheStatus subxidStatus
Definition: proc.h:198
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:859
#define THRESHOLD_SUBTRANS_CLOG_OPT
Definition: clog.c:81
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1380
struct XidCache subxids
Definition: proc.h:200
#define PGPROC_MAX_CACHED_SUBXIDS
Definition: proc.h:36
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:124
static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:338
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ TransactionIdSetPageStatusInternal()

static void TransactionIdSetPageStatusInternal ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn,
int  pageno 
)
static

Definition at line 338 of file clog.c.

References Assert, i, LW_EXCLUSIVE, LWLockHeldByMeInMode(), SimpleLruReadPage(), TRANSACTION_STATUS_ABORTED, TRANSACTION_STATUS_COMMITTED, TRANSACTION_STATUS_SUB_COMMITTED, TransactionIdIsValid, TransactionIdSetStatusBit(), TransactionIdToPage, XactCtl, and XLogRecPtrIsInvalid.

Referenced by TransactionGroupUpdateXidStatus(), and TransactionIdSetPageStatus().

341 {
342  int slotno;
343  int i;
344 
348  Assert(LWLockHeldByMeInMode(XactSLRULock, LW_EXCLUSIVE));
349 
350  /*
351  * If we're doing an async commit (ie, lsn is valid), then we must wait
352  * for any active write on the page slot to complete. Otherwise our
353  * update could reach disk in that write, which will not do since we
354  * mustn't let it reach disk until we've done the appropriate WAL flush.
355  * But when lsn is invalid, it's OK to scribble on a page while it is
356  * write-busy, since we don't care if the update reaches disk sooner than
357  * we think.
358  */
359  slotno = SimpleLruReadPage(XactCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
360 
361  /*
362  * Set the main transaction id, if any.
363  *
364  * If we update more than one xid on this page while it is being written
365  * out, we might find that some of the bits go to disk and others don't.
366  * If we are updating commits on the page with the top-level xid that
367  * could break atomicity, so we subcommit the subxids first before we mark
368  * the top-level commit.
369  */
370  if (TransactionIdIsValid(xid))
371  {
372  /* Subtransactions first, if needed ... */
374  {
375  for (i = 0; i < nsubxids; i++)
376  {
377  Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
378  TransactionIdSetStatusBit(subxids[i],
380  lsn, slotno);
381  }
382  }
383 
384  /* ... then the main transaction */
385  TransactionIdSetStatusBit(xid, status, lsn, slotno);
386  }
387 
388  /* Set the subtransactions */
389  for (i = 0; i < nsubxids; i++)
390  {
391  Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
392  TransactionIdSetStatusBit(subxids[i], status, lsn, slotno);
393  }
394 
395  XactCtl->shared->page_dirty[slotno] = true;
396 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1946
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:27
static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)
Definition: clog.c:564
#define XactCtl
Definition: clog.c:88
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:382
#define TRANSACTION_STATUS_ABORTED
Definition: clog.h:28
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:29
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:745
int i
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ TransactionIdSetStatusBit()

static void TransactionIdSetStatusBit ( TransactionId  xid,
XidStatus  status,
XLogRecPtr  lsn,
int  slotno 
)
static

Definition at line 564 of file clog.c.

References Assert, CLOG_BITS_PER_XACT, CLOG_XACT_BITMASK, GetLSNIndex, InRecovery, TRANSACTION_STATUS_COMMITTED, TRANSACTION_STATUS_IN_PROGRESS, TRANSACTION_STATUS_SUB_COMMITTED, TransactionIdToBIndex, TransactionIdToByte, XactCtl, and XLogRecPtrIsInvalid.

Referenced by TransactionIdSetPageStatusInternal().

565 {
566  int byteno = TransactionIdToByte(xid);
567  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
568  char *byteptr;
569  char byteval;
570  char curval;
571 
572  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
573  curval = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
574 
575  /*
576  * When replaying transactions during recovery we still need to perform
577  * the two phases of subcommit and then commit. However, some transactions
578  * are already correctly marked, so we just treat those as a no-op which
579  * allows us to keep the following Assert as restrictive as possible.
580  */
583  return;
584 
585  /*
586  * Current state change should be from 0 or subcommitted to target state
587  * or we should already be there when replaying changes during recovery.
588  */
589  Assert(curval == 0 ||
592  curval == status);
593 
594  /* note this assumes exclusive access to the clog page */
595  byteval = *byteptr;
596  byteval &= ~(((1 << CLOG_BITS_PER_XACT) - 1) << bshift);
597  byteval |= (status << bshift);
598  *byteptr = byteval;
599 
600  /*
601  * Update the group LSN if the transaction completion LSN is higher.
602  *
603  * Note: lsn will be invalid when supplied during InRecovery processing,
604  * so we don't need to do anything special to avoid LSN updates during
605  * recovery. After recovery completes the next clog change will set the
606  * LSN correctly.
607  */
608  if (!XLogRecPtrIsInvalid(lsn))
609  {
610  int lsnindex = GetLSNIndex(slotno, xid);
611 
612  if (XactCtl->shared->group_lsn[lsnindex] < lsn)
613  XactCtl->shared->group_lsn[lsnindex] = lsn;
614  }
615 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:67
#define CLOG_XACT_BITMASK
Definition: clog.c:62
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:27
#define GetLSNIndex(slotno, xid)
Definition: clog.c:73
bool InRecovery
Definition: xlog.c:204
#define XactCtl
Definition: clog.c:88
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:29
#define CLOG_BITS_PER_XACT
Definition: clog.c:59
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:745
#define TransactionIdToByte(xid)
Definition: clog.c:66
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:26

◆ TransactionIdSetTreeStatus()

void TransactionIdSetTreeStatus ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn 
)

Definition at line 163 of file clog.c.

References Assert, i, set_status_by_pages(), TRANSACTION_STATUS_ABORTED, TRANSACTION_STATUS_COMMITTED, TRANSACTION_STATUS_SUB_COMMITTED, TransactionIdSetPageStatus(), and TransactionIdToPage.

Referenced by TransactionIdAbortTree(), TransactionIdAsyncCommitTree(), and TransactionIdCommitTree().

165 {
166  int pageno = TransactionIdToPage(xid); /* get page of parent */
167  int i;
168 
171 
172  /*
173  * See how many subxids, if any, are on the same page as the parent, if
174  * any.
175  */
176  for (i = 0; i < nsubxids; i++)
177  {
178  if (TransactionIdToPage(subxids[i]) != pageno)
179  break;
180  }
181 
182  /*
183  * Do all items fit on a single page?
184  */
185  if (i == nsubxids)
186  {
187  /*
188  * Set the parent and all subtransactions in a single call
189  */
190  TransactionIdSetPageStatus(xid, nsubxids, subxids, status, lsn,
191  pageno, true);
192  }
193  else
194  {
195  int nsubxids_on_first_page = i;
196 
197  /*
198  * If this is a commit then we care about doing this correctly (i.e.
199  * using the subcommitted intermediate status). By here, we know
200  * we're updating more than one page of clog, so we must mark entries
201  * that are *not* on the first page so that they show as subcommitted
202  * before we then return to update the status to fully committed.
203  *
204  * To avoid touching the first page twice, skip marking subcommitted
205  * for the subxids on that first page.
206  */
208  set_status_by_pages(nsubxids - nsubxids_on_first_page,
209  subxids + nsubxids_on_first_page,
211 
212  /*
213  * Now set the parent and subtransactions on same page as the parent,
214  * if any
215  */
216  pageno = TransactionIdToPage(xid);
217  TransactionIdSetPageStatus(xid, nsubxids_on_first_page, subxids, status,
218  lsn, pageno, false);
219 
220  /*
221  * Now work through the rest of the subxids one clog page at a time,
222  * starting from the second page onwards, like we did above.
223  */
224  set_status_by_pages(nsubxids - nsubxids_on_first_page,
225  subxids + nsubxids_on_first_page,
226  status, lsn);
227  }
228 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:27
#define TRANSACTION_STATUS_ABORTED
Definition: clog.h:28
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:29
static void set_status_by_pages(int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
Definition: clog.c:237
#define Assert(condition)
Definition: c.h:745
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno, bool all_xact_same_page)
Definition: clog.c:273
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225

◆ TrimCLOG()

void TrimCLOG ( void  )

Definition at line 766 of file clog.c.

References CLOG_BITS_PER_XACT, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MemSet, VariableCacheData::nextXid, ShmemVariableCache, SimpleLruReadPage(), TransactionIdToBIndex, TransactionIdToByte, TransactionIdToPage, TransactionIdToPgIndex, XactCtl, and XidFromFullTransactionId.

Referenced by StartupXLOG().

767 {
769  int pageno = TransactionIdToPage(xid);
770 
771  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
772 
773  /*
774  * Re-Initialize our idea of the latest page number.
775  */
776  XactCtl->shared->latest_page_number = pageno;
777 
778  /*
779  * Zero out the remainder of the current clog page. Under normal
780  * circumstances it should be zeroes already, but it seems at least
781  * theoretically possible that XLOG replay will have settled on a nextXID
782  * value that is less than the last XID actually used and marked by the
783  * previous database lifecycle (since subtransaction commit writes clog
784  * but makes no WAL entry). Let's just be safe. (We need not worry about
785  * pages beyond the current one, since those will be zeroed when first
786  * used. For the same reason, there is no need to do anything when
787  * nextXid is exactly at a page boundary; and it's likely that the
788  * "current" page doesn't exist yet in that case.)
789  */
790  if (TransactionIdToPgIndex(xid) != 0)
791  {
792  int byteno = TransactionIdToByte(xid);
793  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
794  int slotno;
795  char *byteptr;
796 
797  slotno = SimpleLruReadPage(XactCtl, pageno, false, xid);
798  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
799 
800  /* Zero so-far-unused positions in the current byte */
801  *byteptr &= (1 << bshift) - 1;
802  /* Zero the rest of the page */
803  MemSet(byteptr + 1, 0, BLCKSZ - byteno - 1);
804 
805  XactCtl->shared->page_dirty[slotno] = true;
806  }
807 
808  LWLockRelease(XactSLRULock);
809 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:67
#define TransactionIdToPage(xid)
Definition: clog.c:64
uint32 TransactionId
Definition: c.h:520
#define TransactionIdToPgIndex(xid)
Definition: clog.c:65
#define XactCtl
Definition: clog.c:88
#define MemSet(start, val, len)
Definition: c.h:949
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:382
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define CLOG_BITS_PER_XACT
Definition: clog.c:59
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1208
#define TransactionIdToByte(xid)
Definition: clog.c:66

◆ TruncateCLOG()

void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 898 of file clog.c.

References AdvanceOldestClogXid(), SimpleLruTruncate(), SlruScanDirCbReportPresence(), SlruScanDirectory(), TransactionIdToPage, WriteTruncateXlogRec(), and XactCtl.

Referenced by vac_truncate_clog().

899 {
900  int cutoffPage;
901 
902  /*
903  * The cutoff point is the start of the segment containing oldestXact. We
904  * pass the *page* containing oldestXact to SimpleLruTruncate.
905  */
906  cutoffPage = TransactionIdToPage(oldestXact);
907 
908  /* Check to see if there's any files that could be removed */
910  return; /* nothing to remove */
911 
912  /*
913  * Advance oldestClogXid before truncating clog, so concurrent xact status
914  * lookups can ensure they don't attempt to access truncated-away clog.
915  *
916  * It's only necessary to do this if we will actually truncate away clog
917  * pages.
918  */
919  AdvanceOldestClogXid(oldestXact);
920 
921  /*
922  * Write XLOG record and flush XLOG to disk. We record the oldest xid
923  * we're keeping information about here so we can ensure that it's always
924  * ahead of clog truncation in case we crash, and so a standby finds out
925  * the new valid xid before the next checkpoint.
926  */
927  WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid);
928 
929  /* Now we can remove the old CLOG segment(s) */
930  SimpleLruTruncate(XactCtl, cutoffPage);
931 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1196
#define XactCtl
Definition: clog.c:88
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
static void WriteTruncateXlogRec(int pageno, TransactionId oldestXact, Oid oldestXactDb)
Definition: clog.c:976
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1352
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1407

◆ WriteTruncateXlogRec()

static void WriteTruncateXlogRec ( int  pageno,
TransactionId  oldestXact,
Oid  oldestXactDb 
)
static

Definition at line 976 of file clog.c.

References CLOG_TRUNCATE, xl_clog_truncate::oldestXact, xl_clog_truncate::oldestXactDb, xl_clog_truncate::pageno, XLogBeginInsert(), XLogFlush(), XLogInsert(), and XLogRegisterData().

Referenced by TruncateCLOG().

977 {
978  XLogRecPtr recptr;
979  xl_clog_truncate xlrec;
980 
981  xlrec.pageno = pageno;
982  xlrec.oldestXact = oldestXact;
983  xlrec.oldestXactDb = oldestXactDb;
984 
985  XLogBeginInsert();
986  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
987  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
988  XLogFlush(recptr);
989 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2844
int pageno
Definition: clog.h:33
#define CLOG_TRUNCATE
Definition: clog.h:55
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
TransactionId oldestXact
Definition: clog.h:34
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXactDb
Definition: clog.h:35
void XLogBeginInsert(void)
Definition: xloginsert.c:123

◆ WriteZeroPageXlogRec()

static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 962 of file clog.c.

References CLOG_ZEROPAGE, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by ZeroCLOGPage().

963 {
964  XLogBeginInsert();
965  XLogRegisterData((char *) (&pageno), sizeof(int));
966  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
967 }
#define CLOG_ZEROPAGE
Definition: clog.h:54
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
void XLogBeginInsert(void)
Definition: xloginsert.c:123

◆ ZeroCLOGPage()

static int ZeroCLOGPage ( int  pageno,
bool  writeXlog 
)
static

Definition at line 730 of file clog.c.

References SimpleLruZeroPage(), WriteZeroPageXlogRec(), and XactCtl.

Referenced by BootStrapCLOG(), clog_redo(), and ExtendCLOG().

731 {
732  int slotno;
733 
734  slotno = SimpleLruZeroPage(XactCtl, pageno);
735 
736  if (writeXlog)
737  WriteZeroPageXlogRec(pageno);
738 
739  return slotno;
740 }
static void WriteZeroPageXlogRec(int pageno)
Definition: clog.c:962
#define XactCtl
Definition: clog.c:88
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
Definition: slru.c:267

Variable Documentation

◆ XactCtlData

SlruCtlData XactCtlData
static

Definition at line 86 of file clog.c.