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 "pgstat.h"
#include "pg_trace.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 ClogCtl   (&ClogCtlData)
 

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 oldestXidDb)
 
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 ClogCtlData
 

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

◆ ClogCtl

◆ 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:445
#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 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().

Function Documentation

◆ BootStrapCLOG()

void BootStrapCLOG ( void  )

Definition at line 712 of file clog.c.

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

Referenced by BootStrapXLOG().

713 {
714  int slotno;
715 
716  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
717 
718  /* Create and zero the first page of the commit log */
719  slotno = ZeroCLOGPage(0, false);
720 
721  /* Make sure it's written out */
722  SimpleLruWritePage(ClogCtl, slotno);
723  Assert(!ClogCtl->shared->page_dirty[slotno]);
724 
725  LWLockRelease(CLogControlLock);
726 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define ClogCtl
Definition: clog.c:88
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:578
#define Assert(condition)
Definition: c.h:670
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:738

◆ CheckPointCLOG()

void CheckPointCLOG ( void  )

Definition at line 842 of file clog.c.

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

Referenced by CheckPointGuts().

843 {
844  /* Flush dirty CLOG pages to disk */
845  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
846  SimpleLruFlush(ClogCtl, true);
847 
848  /*
849  * fsync pg_xact to ensure that any files flushed previously are durably
850  * on disk.
851  */
852  fsync_fname("pg_xact", true);
853 
854  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
855 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:572
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1103
#define ClogCtl
Definition: clog.c:88

◆ clog_redo()

void clog_redo ( XLogReaderState record)

Definition at line 1003 of file clog.c.

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

1004 {
1005  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1006 
1007  /* Backup blocks are not used in clog records */
1008  Assert(!XLogRecHasAnyBlockRefs(record));
1009 
1010  if (info == CLOG_ZEROPAGE)
1011  {
1012  int pageno;
1013  int slotno;
1014 
1015  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
1016 
1017  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
1018 
1019  slotno = ZeroCLOGPage(pageno, false);
1020  SimpleLruWritePage(ClogCtl, slotno);
1021  Assert(!ClogCtl->shared->page_dirty[slotno]);
1022 
1023  LWLockRelease(CLogControlLock);
1024  }
1025  else if (info == CLOG_TRUNCATE)
1026  {
1027  xl_clog_truncate xlrec;
1028 
1029  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
1030 
1031  /*
1032  * During XLOG replay, latest_page_number isn't set up yet; insert a
1033  * suitable value to bypass the sanity test in SimpleLruTruncate.
1034  */
1035  ClogCtl->shared->latest_page_number = xlrec.pageno;
1036 
1038 
1040  }
1041  else
1042  elog(PANIC, "clog_redo: unknown op code %u", info);
1043 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1168
unsigned char uint8
Definition: c.h:294
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define ClogCtl
Definition: clog.c:88
#define CLOG_ZEROPAGE
Definition: clog.h:54
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:271
#define XLogRecGetData(decoder)
Definition: xlogreader.h:226
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:578
int pageno
Definition: clog.h:33
#define CLOG_TRUNCATE
Definition: clog.h:55
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:222
TransactionId oldestXact
Definition: clog.h:34
#define Assert(condition)
Definition: c.h:670
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:738
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:228
#define elog
Definition: elog.h:219

◆ CLOGPagePrecedes()

static bool CLOGPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 952 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

953 {
954  TransactionId xid1;
955  TransactionId xid2;
956 
957  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
958  xid1 += FirstNormalTransactionId;
959  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
960  xid2 += FirstNormalTransactionId;
961 
962  return TransactionIdPrecedes(xid1, xid2);
963 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:61
uint32 TransactionId
Definition: c.h:445
#define FirstNormalTransactionId
Definition: transam.h:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300

◆ CLOGShmemBuffers()

Size CLOGShmemBuffers ( void  )

Definition at line 683 of file clog.c.

References Max, Min, and NBuffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

684 {
685  return Min(128, Max(4, NBuffers / 512));
686 }
#define Min(x, y)
Definition: c.h:802
#define Max(x, y)
Definition: c.h:796
int NBuffers
Definition: globals.c:122

◆ CLOGShmemInit()

void CLOGShmemInit ( void  )

Definition at line 698 of file clog.c.

References CLOG_LSNS_PER_PAGE, ClogCtl, CLOGPagePrecedes(), CLOGShmemBuffers(), LWTRANCHE_CLOG_BUFFERS, and SimpleLruInit().

Referenced by CreateSharedMemoryAndSemaphores().

699 {
700  ClogCtl->PagePrecedes = CLOGPagePrecedes;
702  CLogControlLock, "pg_xact", LWTRANCHE_CLOG_BUFFERS);
703 }
#define ClogCtl
Definition: clog.c:88
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:71
static bool CLOGPagePrecedes(int page1, int page2)
Definition: clog.c:952
Size CLOGShmemBuffers(void)
Definition: clog.c:683
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
Definition: slru.c:165

◆ CLOGShmemSize()

Size CLOGShmemSize ( void  )

Definition at line 692 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

693 {
695 }
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:145
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:71
Size CLOGShmemBuffers(void)
Definition: clog.c:683

◆ ExtendCLOG()

void ExtendCLOG ( TransactionId  newestXact)

Definition at line 867 of file clog.c.

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

Referenced by GetNewTransactionId().

868 {
869  int pageno;
870 
871  /*
872  * No work except at first XID of a page. But beware: just after
873  * wraparound, the first XID of page zero is FirstNormalTransactionId.
874  */
875  if (TransactionIdToPgIndex(newestXact) != 0 &&
877  return;
878 
879  pageno = TransactionIdToPage(newestXact);
880 
881  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
882 
883  /* Zero the page and make an XLOG entry about it */
884  ZeroCLOGPage(pageno, true);
885 
886  LWLockRelease(CLogControlLock);
887 }
#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:1721
#define FirstNormalTransactionId
Definition: transam.h:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:738

◆ 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:670
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 823 of file clog.c.

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

Referenced by ShutdownXLOG().

824 {
825  /* Flush dirty CLOG pages to disk */
826  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(false);
827  SimpleLruFlush(ClogCtl, false);
828 
829  /*
830  * fsync pg_xact to ensure that any files flushed previously are durably
831  * on disk.
832  */
833  fsync_fname("pg_xact", true);
834 
835  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(false);
836 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:572
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1103
#define ClogCtl
Definition: clog.c:88

◆ StartupCLOG()

void StartupCLOG ( void  )

Definition at line 755 of file clog.c.

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

Referenced by StartupXLOG().

756 {
758  int pageno = TransactionIdToPage(xid);
759 
760  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
761 
762  /*
763  * Initialize our idea of the latest page number.
764  */
765  ClogCtl->shared->latest_page_number = pageno;
766 
767  LWLockRelease(CLogControlLock);
768 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
uint32 TransactionId
Definition: c.h:445
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define ClogCtl
Definition: clog.c:88
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117

◆ TransactionGroupUpdateXidStatus()

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

Definition at line 420 of file clog.c.

References PROC_HDR::allPgXact, PROC_HDR::allProcs, Assert, PROC_HDR::clogGroupFirst, PGPROC::clogGroupMember, PGPROC::clogGroupMemberLsn, PGPROC::clogGroupMemberPage, PGPROC::clogGroupMemberXid, PGPROC::clogGroupMemberXidStatus, PGPROC::clogGroupNext, INVALID_PGPROCNO, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MyProc, PGXACT::nxids, PGXACT::overflowed, 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, TransactionIdIsValid, TransactionIdSetPageStatusInternal(), WAIT_EVENT_CLOG_GROUP_UPDATE, and XidCache::xids.

Referenced by TransactionIdSetPageStatus().

422 {
423  volatile PROC_HDR *procglobal = ProcGlobal;
424  PGPROC *proc = MyProc;
425  uint32 nextidx;
426  uint32 wakeidx;
427 
428  /* We should definitely have an XID whose status needs to be updated. */
430 
431  /*
432  * Add ourselves to the list of processes needing a group XID status
433  * update.
434  */
435  proc->clogGroupMember = true;
436  proc->clogGroupMemberXid = xid;
438  proc->clogGroupMemberPage = pageno;
439  proc->clogGroupMemberLsn = lsn;
440 
441  nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst);
442 
443  while (true)
444  {
445  /*
446  * Add the proc to list, if the clog page where we need to update the
447  * current transaction status is same as group leader's clog page.
448  *
449  * There is a race condition here, which is that after doing the below
450  * check and before adding this proc's clog update to a group, the
451  * group leader might have already finished the group update for this
452  * page and becomes group leader of another group. This will lead to a
453  * situation where a single group can have different clog page
454  * updates. This isn't likely and will still work, just maybe a bit
455  * less efficiently.
456  */
457  if (nextidx != INVALID_PGPROCNO &&
459  {
460  proc->clogGroupMember = false;
461  return false;
462  }
463 
464  pg_atomic_write_u32(&proc->clogGroupNext, nextidx);
465 
467  &nextidx,
468  (uint32) proc->pgprocno))
469  break;
470  }
471 
472  /*
473  * If the list was not empty, the leader will update the status of our
474  * XID. It is impossible to have followers without a leader because the
475  * first process that has added itself to the list will always have
476  * nextidx as INVALID_PGPROCNO.
477  */
478  if (nextidx != INVALID_PGPROCNO)
479  {
480  int extraWaits = 0;
481 
482  /* Sleep until the leader updates our XID status. */
484  for (;;)
485  {
486  /* acts as a read barrier */
487  PGSemaphoreLock(proc->sem);
488  if (!proc->clogGroupMember)
489  break;
490  extraWaits++;
491  }
493 
495 
496  /* Fix semaphore count for any absorbed wakeups */
497  while (extraWaits-- > 0)
498  PGSemaphoreUnlock(proc->sem);
499  return true;
500  }
501 
502  /* We are the leader. Acquire the lock on behalf of everyone. */
503  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
504 
505  /*
506  * Now that we've got the lock, clear the list of processes waiting for
507  * group XID status update, saving a pointer to the head of the list.
508  * Trying to pop elements one at a time could lead to an ABA problem.
509  */
510  nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst,
512 
513  /* Remember head of list so we can perform wakeups after dropping lock. */
514  wakeidx = nextidx;
515 
516  /* Walk the list and update the status of all XIDs. */
517  while (nextidx != INVALID_PGPROCNO)
518  {
519  PGPROC *proc = &ProcGlobal->allProcs[nextidx];
520  PGXACT *pgxact = &ProcGlobal->allPgXact[nextidx];
521 
522  /*
523  * Overflowed transactions should not use group XID status update
524  * mechanism.
525  */
526  Assert(!pgxact->overflowed);
527 
529  pgxact->nxids,
530  proc->subxids.xids,
532  proc->clogGroupMemberLsn,
533  proc->clogGroupMemberPage);
534 
535  /* Move to next proc in list. */
536  nextidx = pg_atomic_read_u32(&proc->clogGroupNext);
537  }
538 
539  /* We're done with the lock now. */
540  LWLockRelease(CLogControlLock);
541 
542  /*
543  * Now that we've released the lock, go back and wake everybody up. We
544  * don't do this under the lock so as to keep lock hold times to a
545  * minimum.
546  */
547  while (wakeidx != INVALID_PGPROCNO)
548  {
549  PGPROC *proc = &ProcGlobal->allProcs[wakeidx];
550 
551  wakeidx = pg_atomic_read_u32(&proc->clogGroupNext);
553 
554  /* ensure all previous writes are visible before follower continues. */
556 
557  proc->clogGroupMember = false;
558 
559  if (proc != MyProc)
560  PGSemaphoreUnlock(proc->sem);
561  }
562 
563  return true;
564 }
XidStatus clogGroupMemberXidStatus
Definition: proc.h:179
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:323
Definition: proc.h:219
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:183
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:322
PGXACT * allPgXact
Definition: proc.h:246
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:80
pg_atomic_uint32 clogGroupNext
Definition: proc.h:177
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:303
int clogGroupMemberPage
Definition: proc.h:181
uint8 nxids
Definition: proc.h:235
TransactionId clogGroupMemberXid
Definition: proc.h:178
unsigned int uint32
Definition: c.h:296
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1244
struct XidCache subxids
Definition: proc.h:159
#define INVALID_PGPROCNO
Definition: proc.h:77
Definition: proc.h:241
bool overflowed
Definition: proc.h:231
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:670
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1220
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:303
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:258
int pgprocno
Definition: proc.h:110
bool clogGroupMember
Definition: proc.h:176
#define pg_write_barrier()
Definition: atomics.h:162
static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:345
PGPROC * allProcs
Definition: proc.h:244
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:269
PGSemaphore sem
Definition: proc.h:101
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
Definition: proc.h:95
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:252

◆ TransactionIdGetStatus()

XidStatus TransactionIdGetStatus ( TransactionId  xid,
XLogRecPtr lsn 
)

Definition at line 641 of file clog.c.

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

Referenced by TransactionIdGetCommitLSN(), and TransactionLogFetch().

642 {
643  int pageno = TransactionIdToPage(xid);
644  int byteno = TransactionIdToByte(xid);
645  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
646  int slotno;
647  int lsnindex;
648  char *byteptr;
650 
651  /* lock is acquired by SimpleLruReadPage_ReadOnly */
652 
653  slotno = SimpleLruReadPage_ReadOnly(ClogCtl, pageno, xid);
654  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
655 
656  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
657 
658  lsnindex = GetLSNIndex(slotno, xid);
659  *lsn = ClogCtl->shared->group_lsn[lsnindex];
660 
661  LWLockRelease(CLogControlLock);
662 
663  return status;
664 }
#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
int XidStatus
Definition: clog.h:24
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define ClogCtl
Definition: clog.c:88
#define CLOG_BITS_PER_XACT
Definition: clog.c:59
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:467
#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 Assert, LW_EXCLUSIVE, LWLockAcquire(), LWLockConditionalAcquire(), LWLockRelease(), MyPgXact, MyProc, PGXACT::nxids, PGPROC_MAX_CACHED_SUBXIDS, StaticAssertStmt, PGPROC::subxids, THRESHOLD_SUBTRANS_CLOG_OPT, TransactionGroupUpdateXidStatus(), TransactionIdSetPageStatusInternal(), PGXACT::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 CLogControlLock, 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
286  * CLogControlLock needs to be acquired is reduced.
287  *
288  * For this optimization to be safe, the XID in MyPgXact and the subxids
289  * in MyProc must be the same as the ones for which we're setting the
290  * status. Check that 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 == MyPgXact->xid &&
297  nsubxids <= THRESHOLD_SUBTRANS_CLOG_OPT &&
298  nsubxids == MyPgXact->nxids &&
299  memcmp(subxids, MyProc->subxids.xids,
300  nsubxids * sizeof(TransactionId)) == 0)
301  {
302  /*
303  * We don't try to do group update optimization if a process has
304  * overflowed the subxids array in its PGPROC, since in that case we
305  * don't have a complete list of XIDs for it.
306  */
308 
309  /*
310  * If we can immediately acquire CLogControlLock, we update the status
311  * of our own XID and release the lock. If not, try use group XID
312  * update. If that doesn't work out, fall back to waiting for the
313  * lock to perform an update for this transaction only.
314  */
315  if (LWLockConditionalAcquire(CLogControlLock, LW_EXCLUSIVE))
316  {
317  /* Got the lock without waiting! Do the update. */
318  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
319  lsn, pageno);
320  LWLockRelease(CLogControlLock);
321  return;
322  }
323  else if (TransactionGroupUpdateXidStatus(xid, status, lsn, pageno))
324  {
325  /* Group update mechanism has done the work. */
326  return;
327  }
328 
329  /* Fall through only if update isn't done yet. */
330  }
331 
332  /* Group update not applicable, or couldn't accept this page number. */
333  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
334  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
335  lsn, pageno);
336  LWLockRelease(CLogControlLock);
337 }
uint32 TransactionId
Definition: c.h:445
static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:420
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:221
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1721
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:753
#define THRESHOLD_SUBTRANS_CLOG_OPT
Definition: clog.c:81
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1289
uint8 nxids
Definition: proc.h:235
struct XidCache subxids
Definition: proc.h:159
#define PGPROC_MAX_CACHED_SUBXIDS
Definition: proc.h:36
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:670
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1117
static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:345
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 345 of file clog.c.

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

Referenced by TransactionGroupUpdateXidStatus(), and TransactionIdSetPageStatus().

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

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

Referenced by TransactionIdSetPageStatusInternal().

573 {
574  int byteno = TransactionIdToByte(xid);
575  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
576  char *byteptr;
577  char byteval;
578  char curval;
579 
580  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
581  curval = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
582 
583  /*
584  * When replaying transactions during recovery we still need to perform
585  * the two phases of subcommit and then commit. However, some transactions
586  * are already correctly marked, so we just treat those as a no-op which
587  * allows us to keep the following Assert as restrictive as possible.
588  */
591  return;
592 
593  /*
594  * Current state change should be from 0 or subcommitted to target state
595  * or we should already be there when replaying changes during recovery.
596  */
597  Assert(curval == 0 ||
600  curval == status);
601 
602  /* note this assumes exclusive access to the clog page */
603  byteval = *byteptr;
604  byteval &= ~(((1 << CLOG_BITS_PER_XACT) - 1) << bshift);
605  byteval |= (status << bshift);
606  *byteptr = byteval;
607 
608  /*
609  * Update the group LSN if the transaction completion LSN is higher.
610  *
611  * Note: lsn will be invalid when supplied during InRecovery processing,
612  * so we don't need to do anything special to avoid LSN updates during
613  * recovery. After recovery completes the next clog change will set the
614  * LSN correctly.
615  */
616  if (!XLogRecPtrIsInvalid(lsn))
617  {
618  int lsnindex = GetLSNIndex(slotno, xid);
619 
620  if (ClogCtl->shared->group_lsn[lsnindex] < lsn)
621  ClogCtl->shared->group_lsn[lsnindex] = lsn;
622  }
623 }
#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:194
#define ClogCtl
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:670
#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:670
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 774 of file clog.c.

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

Referenced by StartupXLOG().

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

◆ TruncateCLOG()

void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 906 of file clog.c.

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

Referenced by vac_truncate_clog().

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

◆ WriteTruncateXlogRec()

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

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

985 {
986  XLogRecPtr recptr;
987  xl_clog_truncate xlrec;
988 
989  xlrec.pageno = pageno;
990  xlrec.oldestXact = oldestXact;
991  xlrec.oldestXactDb = oldestXactDb;
992 
993  XLogBeginInsert();
994  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
995  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
996  XLogFlush(recptr);
997 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2763
int pageno
Definition: clog.h:33
#define CLOG_TRUNCATE
Definition: clog.h:55
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
TransactionId oldestXact
Definition: clog.h:34
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXactDb
Definition: clog.h:35
void XLogBeginInsert(void)
Definition: xloginsert.c:120

◆ WriteZeroPageXlogRec()

static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 970 of file clog.c.

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

Referenced by ZeroCLOGPage().

971 {
972  XLogBeginInsert();
973  XLogRegisterData((char *) (&pageno), sizeof(int));
974  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
975 }
#define CLOG_ZEROPAGE
Definition: clog.h:54
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void XLogBeginInsert(void)
Definition: xloginsert.c:120

◆ ZeroCLOGPage()

static int ZeroCLOGPage ( int  pageno,
bool  writeXlog 
)
static

Definition at line 738 of file clog.c.

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

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

739 {
740  int slotno;
741 
742  slotno = SimpleLruZeroPage(ClogCtl, pageno);
743 
744  if (writeXlog)
745  WriteZeroPageXlogRec(pageno);
746 
747  return slotno;
748 }
static void WriteZeroPageXlogRec(int pageno)
Definition: clog.c:970
#define ClogCtl
Definition: clog.c:88
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
Definition: slru.c:263

Variable Documentation

◆ ClogCtlData

SlruCtlData ClogCtlData
static

Definition at line 86 of file clog.c.