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 "storage/sync.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 CheckPointCLOG (void)
 
void ExtendCLOG (TransactionId newestXact)
 
void TruncateCLOG (TransactionId oldestXact, Oid oldestxid_datoid)
 
void clog_redo (XLogReaderState *record)
 
int clogsyncfiletag (const FileTag *ftag, char *path)
 

Variables

static SlruCtlData XactCtlData
 

Macro Definition Documentation

◆ CLOG_BITS_PER_XACT

#define CLOG_BITS_PER_XACT   2

Definition at line 60 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 72 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 63 of file clog.c.

Referenced by TransactionIdGetStatus(), and TransactionIdSetStatusBit().

◆ CLOG_XACTS_PER_BYTE

#define CLOG_XACTS_PER_BYTE   4

Definition at line 61 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 71 of file clog.c.

◆ CLOG_XACTS_PER_PAGE

#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)

Definition at line 62 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:62
uint32 TransactionId
Definition: c.h:521
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:72
#define CLOG_XACTS_PER_LSN_GROUP
Definition: clog.c:71

Definition at line 74 of file clog.c.

Referenced by TransactionIdGetStatus(), and TransactionIdSetStatusBit().

◆ THRESHOLD_SUBTRANS_CLOG_OPT

#define THRESHOLD_SUBTRANS_CLOG_OPT   5

Definition at line 82 of file clog.c.

Referenced by TransactionGroupUpdateXidStatus(), and TransactionIdSetPageStatus().

◆ TransactionIdToBIndex

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

Definition at line 68 of file clog.c.

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

◆ TransactionIdToByte

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

Definition at line 67 of file clog.c.

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

◆ TransactionIdToPage

◆ TransactionIdToPgIndex

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

Definition at line 66 of file clog.c.

Referenced by ExtendCLOG(), and TrimCLOG().

◆ XactCtl

Function Documentation

◆ BootStrapCLOG()

void BootStrapCLOG ( void  )

Definition at line 706 of file clog.c.

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

Referenced by BootStrapXLOG().

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

◆ CheckPointCLOG()

void CheckPointCLOG ( void  )

Definition at line 817 of file clog.c.

References SimpleLruWriteAll(), and XactCtl.

Referenced by CheckPointGuts().

818 {
819  /*
820  * Write dirty CLOG pages to disk. This may result in sync requests
821  * queued for later handling by ProcessSyncRequests(), as part of the
822  * checkpoint.
823  */
824  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
825  SimpleLruWriteAll(XactCtl, true);
826  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
827 }
#define XactCtl
Definition: clog.c:89
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1155

◆ clog_redo()

void clog_redo ( XLogReaderState record)

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

976 {
977  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
978 
979  /* Backup blocks are not used in clog records */
980  Assert(!XLogRecHasAnyBlockRefs(record));
981 
982  if (info == CLOG_ZEROPAGE)
983  {
984  int pageno;
985  int slotno;
986 
987  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
988 
989  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
990 
991  slotno = ZeroCLOGPage(pageno, false);
992  SimpleLruWritePage(XactCtl, slotno);
993  Assert(!XactCtl->shared->page_dirty[slotno]);
994 
995  LWLockRelease(XactSLRULock);
996  }
997  else if (info == CLOG_TRUNCATE)
998  {
999  xl_clog_truncate xlrec;
1000 
1001  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
1002 
1003  /*
1004  * During XLOG replay, latest_page_number isn't set up yet; insert a
1005  * suitable value to bypass the sanity test in SimpleLruTruncate.
1006  */
1007  XactCtl->shared->latest_page_number = xlrec.pageno;
1008 
1010 
1012  }
1013  else
1014  elog(PANIC, "clog_redo: unknown op code %u", info);
1015 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1225
#define XactCtl
Definition: clog.c:89
unsigned char uint8
Definition: c.h:373
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define CLOG_ZEROPAGE
Definition: clog.h:57
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:613
int pageno
Definition: clog.h:34
#define CLOG_TRUNCATE
Definition: clog.h:58
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:305
TransactionId oldestXact
Definition: clog.h:35
#define Assert(condition)
Definition: c.h:746
#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:732
#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 924 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

925 {
926  TransactionId xid1;
927  TransactionId xid2;
928 
929  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
930  xid1 += FirstNormalTransactionId;
931  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
932  xid2 += FirstNormalTransactionId;
933 
934  return TransactionIdPrecedes(xid1, xid2);
935 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:62
uint32 TransactionId
Definition: c.h:521
#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:928
#define Max(x, y)
Definition: c.h:922
int NBuffers
Definition: globals.c:132

◆ CLOGShmemInit()

void CLOGShmemInit ( void  )

Definition at line 691 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

692 {
693  XactCtl->PagePrecedes = CLOGPagePrecedes;
695  XactSLRULock, "pg_xact", LWTRANCHE_XACT_BUFFER,
697 }
#define XactCtl
Definition: clog.c:89
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id, SyncRequestHandler sync_handler)
Definition: slru.c:186
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:72
static bool CLOGPagePrecedes(int page1, int page2)
Definition: clog.c:924
Size CLOGShmemBuffers(void)
Definition: clog.c:676

◆ 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:155
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:72
Size CLOGShmemBuffers(void)
Definition: clog.c:676

◆ clogsyncfiletag()

int clogsyncfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1021 of file clog.c.

References SlruSyncFileTag(), and XactCtl.

1022 {
1023  return SlruSyncFileTag(XactCtl, ftag, path);
1024 }
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
Definition: slru.c:1489
#define XactCtl
Definition: clog.c:89

◆ ExtendCLOG()

void ExtendCLOG ( TransactionId  newestXact)

Definition at line 839 of file clog.c.

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

Referenced by GetNewTransactionId().

840 {
841  int pageno;
842 
843  /*
844  * No work except at first XID of a page. But beware: just after
845  * wraparound, the first XID of page zero is FirstNormalTransactionId.
846  */
847  if (TransactionIdToPgIndex(newestXact) != 0 &&
849  return;
850 
851  pageno = TransactionIdToPage(newestXact);
852 
853  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
854 
855  /* Zero the page and make an XLOG entry about it */
856  ZeroCLOGPage(pageno, true);
857 
858  LWLockRelease(XactSLRULock);
859 }
#define TransactionIdToPage(xid)
Definition: clog.c:65
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define TransactionIdToPgIndex(xid)
Definition: clog.c:66
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:732

◆ set_status_by_pages()

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

Definition at line 238 of file clog.c.

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

Referenced by TransactionIdSetTreeStatus().

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

◆ StartupCLOG()

void StartupCLOG ( void  )

Definition at line 749 of file clog.c.

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

Referenced by StartupXLOG().

750 {
752  int pageno = TransactionIdToPage(xid);
753 
754  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
755 
756  /*
757  * Initialize our idea of the latest page number.
758  */
759  XactCtl->shared->latest_page_number = pageno;
760 
761  LWLockRelease(XactSLRULock);
762 }
#define TransactionIdToPage(xid)
Definition: clog.c:65
uint32 TransactionId
Definition: c.h:521
#define XactCtl
Definition: clog.c:89
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 414 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().

416 {
417  volatile PROC_HDR *procglobal = ProcGlobal;
418  PGPROC *proc = MyProc;
419  uint32 nextidx;
420  uint32 wakeidx;
421 
422  /* We should definitely have an XID whose status needs to be updated. */
424 
425  /*
426  * Add ourselves to the list of processes needing a group XID status
427  * update.
428  */
429  proc->clogGroupMember = true;
430  proc->clogGroupMemberXid = xid;
432  proc->clogGroupMemberPage = pageno;
433  proc->clogGroupMemberLsn = lsn;
434 
435  nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst);
436 
437  while (true)
438  {
439  /*
440  * Add the proc to list, if the clog page where we need to update the
441  * current transaction status is same as group leader's clog page.
442  *
443  * There is a race condition here, which is that after doing the below
444  * check and before adding this proc's clog update to a group, the
445  * group leader might have already finished the group update for this
446  * page and becomes group leader of another group. This will lead to a
447  * situation where a single group can have different clog page
448  * updates. This isn't likely and will still work, just maybe a bit
449  * less efficiently.
450  */
451  if (nextidx != INVALID_PGPROCNO &&
453  {
454  proc->clogGroupMember = false;
455  return false;
456  }
457 
458  pg_atomic_write_u32(&proc->clogGroupNext, nextidx);
459 
461  &nextidx,
462  (uint32) proc->pgprocno))
463  break;
464  }
465 
466  /*
467  * If the list was not empty, the leader will update the status of our
468  * XID. It is impossible to have followers without a leader because the
469  * first process that has added itself to the list will always have
470  * nextidx as INVALID_PGPROCNO.
471  */
472  if (nextidx != INVALID_PGPROCNO)
473  {
474  int extraWaits = 0;
475 
476  /* Sleep until the leader updates our XID status. */
478  for (;;)
479  {
480  /* acts as a read barrier */
481  PGSemaphoreLock(proc->sem);
482  if (!proc->clogGroupMember)
483  break;
484  extraWaits++;
485  }
487 
489 
490  /* Fix semaphore count for any absorbed wakeups */
491  while (extraWaits-- > 0)
492  PGSemaphoreUnlock(proc->sem);
493  return true;
494  }
495 
496  /* We are the leader. Acquire the lock on behalf of everyone. */
497  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
498 
499  /*
500  * Now that we've got the lock, clear the list of processes waiting for
501  * group XID status update, saving a pointer to the head of the list.
502  * Trying to pop elements one at a time could lead to an ABA problem.
503  */
504  nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst,
506 
507  /* Remember head of list so we can perform wakeups after dropping lock. */
508  wakeidx = nextidx;
509 
510  /* Walk the list and update the status of all XIDs. */
511  while (nextidx != INVALID_PGPROCNO)
512  {
513  PGPROC *proc = &ProcGlobal->allProcs[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  proc->subxidStatus.count,
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(XactSLRULock);
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: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:82
int clogGroupMemberPage
Definition: proc.h:222
TransactionId clogGroupMemberXid
Definition: proc.h:219
unsigned int uint32
Definition: c.h:375
static void pgstat_report_wait_end(void)
Definition: pgstat.h:1466
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:746
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: pgstat.h:1442
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:339
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:227
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 634 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().

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(XactCtl, pageno, xid);
647  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
648 
649  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
650 
651  lsnindex = GetLSNIndex(slotno, xid);
652  *lsn = XactCtl->shared->group_lsn[lsnindex];
653 
654  LWLockRelease(XactSLRULock);
655 
656  return status;
657 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:68
#define CLOG_XACT_BITMASK
Definition: clog.c:63
#define TransactionIdToPage(xid)
Definition: clog.c:65
#define GetLSNIndex(slotno, xid)
Definition: clog.c:74
#define XactCtl
Definition: clog.c:89
int XidStatus
Definition: clog.h:25
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1812
#define CLOG_BITS_PER_XACT
Definition: clog.c:60
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:494
#define TransactionIdToByte(xid)
Definition: clog.c:67
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227

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

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

◆ TransactionIdSetPageStatusInternal()

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

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

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

◆ 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, GetLSNIndex, InRecovery, TRANSACTION_STATUS_COMMITTED, TRANSACTION_STATUS_IN_PROGRESS, TRANSACTION_STATUS_SUB_COMMITTED, TransactionIdToBIndex, TransactionIdToByte, XactCtl, 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 = XactCtl->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 (XactCtl->shared->group_lsn[lsnindex] < lsn)
614  XactCtl->shared->group_lsn[lsnindex] = lsn;
615  }
616 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:68
#define CLOG_XACT_BITMASK
Definition: clog.c:63
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:28
#define GetLSNIndex(slotno, xid)
Definition: clog.c:74
bool InRecovery
Definition: xlog.c:205
#define XactCtl
Definition: clog.c:89
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:30
#define CLOG_BITS_PER_XACT
Definition: clog.c:60
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:746
#define TransactionIdToByte(xid)
Definition: clog.c:67
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:27

◆ TransactionIdSetTreeStatus()

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

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

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

◆ TrimCLOG()

void TrimCLOG ( void  )

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

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

◆ TruncateCLOG()

void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 878 of file clog.c.

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

Referenced by vac_truncate_clog().

879 {
880  int cutoffPage;
881 
882  /*
883  * The cutoff point is the start of the segment containing oldestXact. We
884  * pass the *page* containing oldestXact to SimpleLruTruncate.
885  */
886  cutoffPage = TransactionIdToPage(oldestXact);
887 
888  /* Check to see if there's any files that could be removed */
890  return; /* nothing to remove */
891 
892  /*
893  * Advance oldestClogXid before truncating clog, so concurrent xact status
894  * lookups can ensure they don't attempt to access truncated-away clog.
895  *
896  * It's only necessary to do this if we will actually truncate away clog
897  * pages.
898  */
899  AdvanceOldestClogXid(oldestXact);
900 
901  /*
902  * Write XLOG record and flush XLOG to disk. We record the oldest xid
903  * we're keeping information about here so we can ensure that it's always
904  * ahead of clog truncation in case we crash, and so a standby finds out
905  * the new valid xid before the next checkpoint.
906  */
907  WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid);
908 
909  /* Now we can remove the old CLOG segment(s) */
910  SimpleLruTruncate(XactCtl, cutoffPage);
911 }
#define TransactionIdToPage(xid)
Definition: clog.c:65
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1225
#define XactCtl
Definition: clog.c:89
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
static void WriteTruncateXlogRec(int pageno, TransactionId oldestXact, Oid oldestXactDb)
Definition: clog.c:956
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1394
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1449

◆ WriteTruncateXlogRec()

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

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

957 {
958  XLogRecPtr recptr;
959  xl_clog_truncate xlrec;
960 
961  xlrec.pageno = pageno;
962  xlrec.oldestXact = oldestXact;
963  xlrec.oldestXactDb = oldestXactDb;
964 
965  XLogBeginInsert();
966  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
967  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
968  XLogFlush(recptr);
969 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2847
int pageno
Definition: clog.h:34
#define CLOG_TRUNCATE
Definition: clog.h:58
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
TransactionId oldestXact
Definition: clog.h:35
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXactDb
Definition: clog.h:36
void XLogBeginInsert(void)
Definition: xloginsert.c:123

◆ WriteZeroPageXlogRec()

static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 942 of file clog.c.

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

Referenced by ZeroCLOGPage().

943 {
944  XLogBeginInsert();
945  XLogRegisterData((char *) (&pageno), sizeof(int));
946  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
947 }
#define CLOG_ZEROPAGE
Definition: clog.h:57
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 732 of file clog.c.

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

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

733 {
734  int slotno;
735 
736  slotno = SimpleLruZeroPage(XactCtl, pageno);
737 
738  if (writeXlog)
739  WriteZeroPageXlogRec(pageno);
740 
741  return slotno;
742 }
static void WriteZeroPageXlogRec(int pageno)
Definition: clog.c:942
#define XactCtl
Definition: clog.c:89
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
Definition: slru.c:279

Variable Documentation

◆ XactCtlData

SlruCtlData XactCtlData
static

Definition at line 87 of file clog.c.