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

Function Documentation

◆ BootStrapCLOG()

void BootStrapCLOG ( void  )

Definition at line 705 of file clog.c.

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

Referenced by BootStrapXLOG().

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

◆ CheckPointCLOG()

void CheckPointCLOG ( void  )

Definition at line 835 of file clog.c.

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

Referenced by CheckPointGuts().

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

◆ clog_redo()

void clog_redo ( XLogReaderState record)

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

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

◆ CLOGPagePrecedes()

static bool CLOGPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 945 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

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

◆ CLOGShmemBuffers()

Size CLOGShmemBuffers ( void  )

Definition at line 676 of file clog.c.

References Max, Min, and NBuffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

677 {
678  return Min(128, Max(4, NBuffers / 512));
679 }
#define Min(x, y)
Definition: c.h:920
#define Max(x, y)
Definition: c.h:914
int NBuffers
Definition: globals.c:131

◆ CLOGShmemInit()

void CLOGShmemInit ( void  )

Definition at line 691 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

692 {
693  ClogCtl->PagePrecedes = CLOGPagePrecedes;
695  CLogControlLock, "pg_xact", LWTRANCHE_CLOG_BUFFERS);
696 }
#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:945
Size CLOGShmemBuffers(void)
Definition: clog.c:676
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
Definition: slru.c:164

◆ CLOGShmemSize()

Size CLOGShmemSize ( void  )

Definition at line 685 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

686 {
688 }
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:676

◆ ExtendCLOG()

void ExtendCLOG ( TransactionId  newestXact)

Definition at line 860 of file clog.c.

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

Referenced by GetNewTransactionId().

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

◆ 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:738
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 816 of file clog.c.

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

Referenced by ShutdownXLOG().

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

◆ StartupCLOG()

void StartupCLOG ( void  )

Definition at line 748 of file clog.c.

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

Referenced by StartupXLOG().

749 {
751  int pageno = TransactionIdToPage(xid);
752 
753  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
754 
755  /*
756  * Initialize our idea of the latest page number.
757  */
758  ClogCtl->shared->latest_page_number = pageno;
759 
760  LWLockRelease(CLogControlLock);
761 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
uint32 TransactionId
Definition: c.h:513
FullTransactionId nextFullXid
Definition: transam.h:164
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
#define ClogCtl
Definition: clog.c:88
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123

◆ TransactionGroupUpdateXidStatus()

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

Definition at line 413 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, 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, THRESHOLD_SUBTRANS_CLOG_OPT, TransactionIdIsValid, TransactionIdSetPageStatusInternal(), WAIT_EVENT_CLOG_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(CLogControlLock, 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  PGXACT *pgxact = &ProcGlobal->allPgXact[nextidx];
514 
515  /*
516  * Transactions with more than THRESHOLD_SUBTRANS_CLOG_OPT sub-XIDs
517  * should not use group XID status update mechanism.
518  */
520 
522  pgxact->nxids,
523  proc->subxids.xids,
525  proc->clogGroupMemberLsn,
526  proc->clogGroupMemberPage);
527 
528  /* Move to next proc in list. */
529  nextidx = pg_atomic_read_u32(&proc->clogGroupNext);
530  }
531 
532  /* We're done with the lock now. */
533  LWLockRelease(CLogControlLock);
534 
535  /*
536  * Now that we've released the lock, go back and wake everybody up. We
537  * don't do this under the lock so as to keep lock hold times to a
538  * minimum.
539  */
540  while (wakeidx != INVALID_PGPROCNO)
541  {
542  PGPROC *proc = &ProcGlobal->allProcs[wakeidx];
543 
544  wakeidx = pg_atomic_read_u32(&proc->clogGroupNext);
546 
547  /* ensure all previous writes are visible before follower continues. */
549 
550  proc->clogGroupMember = false;
551 
552  if (proc != MyProc)
553  PGSemaphoreUnlock(proc->sem);
554  }
555 
556  return true;
557 }
XidStatus clogGroupMemberXidStatus
Definition: proc.h:182
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:340
Definition: proc.h:222
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:186
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:311
PGXACT * allPgXact
Definition: proc.h:249
PGPROC * MyProc
Definition: proc.c:67
PROC_HDR * ProcGlobal
Definition: proc.c:80
pg_atomic_uint32 clogGroupNext
Definition: proc.h:180
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
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:184
uint8 nxids
Definition: proc.h:238
TransactionId clogGroupMemberXid
Definition: proc.h:181
unsigned int uint32
Definition: c.h:367
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1344
struct XidCache subxids
Definition: proc.h:162
#define INVALID_PGPROCNO
Definition: proc.h:77
Definition: proc.h:244
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
#define Assert(condition)
Definition: c.h:738
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1320
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:320
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:263
int pgprocno
Definition: proc.h:110
bool clogGroupMember
Definition: proc.h:179
#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:247
#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: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:241

◆ TransactionIdGetStatus()

XidStatus TransactionIdGetStatus ( TransactionId  xid,
XLogRecPtr lsn 
)

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

635 {
636  int pageno = TransactionIdToPage(xid);
637  int byteno = TransactionIdToByte(xid);
638  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
639  int slotno;
640  int lsnindex;
641  char *byteptr;
643 
644  /* lock is acquired by SimpleLruReadPage_ReadOnly */
645 
646  slotno = SimpleLruReadPage_ReadOnly(ClogCtl, pageno, xid);
647  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
648 
649  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
650 
651  lsnindex = GetLSNIndex(slotno, xid);
652  *lsn = ClogCtl->shared->group_lsn[lsnindex];
653 
654  LWLockRelease(CLogControlLock);
655 
656  return status;
657 }
#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:1727
#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:466
#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 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  * If we can immediately acquire CLogControlLock, we update the status
304  * of 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(CLogControlLock, LW_EXCLUSIVE))
309  {
310  /* Got the lock without waiting! Do the update. */
311  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
312  lsn, pageno);
313  LWLockRelease(CLogControlLock);
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(CLogControlLock, LW_EXCLUSIVE);
327  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
328  lsn, pageno);
329  LWLockRelease(CLogControlLock);
330 }
uint32 TransactionId
Definition: c.h:513
static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:413
PGPROC * MyProc
Definition: proc.c:67
TransactionId xid
Definition: proc.h:224
PGXACT * MyPgXact
Definition: proc.c:68
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1727
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:852
#define THRESHOLD_SUBTRANS_CLOG_OPT
Definition: clog.c:81
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1295
uint8 nxids
Definition: proc.h:238
struct XidCache subxids
Definition: proc.h:162
#define PGPROC_MAX_CACHED_SUBXIDS
Definition: proc.h:36
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:40
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1123
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, 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().

341 {
342  int slotno;
343  int i;
344 
348  Assert(LWLockHeldByMeInMode(CLogControlLock, 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(ClogCtl, 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(ClogCtl->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(ClogCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
392  TransactionIdSetStatusBit(subxids[i], status, lsn, slotno);
393  }
394 
395  ClogCtl->shared->page_dirty[slotno] = true;
396 }
#define TransactionIdToPage(xid)
Definition: clog.c:64
bool LWLockHeldByMeInMode(LWLock *l, LWLockMode mode)
Definition: lwlock.c:1861
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:27
static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)
Definition: clog.c:565
#define ClogCtl
Definition: clog.c:88
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:374
#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:738
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 565 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().

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

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

Referenced by StartupXLOG().

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

◆ TruncateCLOG()

void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 899 of file clog.c.

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

Referenced by vac_truncate_clog().

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

◆ WriteTruncateXlogRec()

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

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

978 {
979  XLogRecPtr recptr;
980  xl_clog_truncate xlrec;
981 
982  xlrec.pageno = pageno;
983  xlrec.oldestXact = oldestXact;
984  xlrec.oldestXactDb = oldestXactDb;
985 
986  XLogBeginInsert();
987  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
988  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
989  XLogFlush(recptr);
990 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2812
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 963 of file clog.c.

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

Referenced by ZeroCLOGPage().

964 {
965  XLogBeginInsert();
966  XLogRegisterData((char *) (&pageno), sizeof(int));
967  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
968 }
#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 731 of file clog.c.

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

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

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

Variable Documentation

◆ ClogCtlData

SlruCtlData ClogCtlData
static

Definition at line 86 of file clog.c.