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(), and CLOGShmemInit().

◆ 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:587
#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 712 of file clog.c.

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

Referenced by BootStrapXLOG().

713 {
714  int slotno;
715 
716  LWLockAcquire(XactSLRULock, 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(XactCtl, slotno);
723  Assert(!XactCtl->shared->page_dirty[slotno]);
724 
725  LWLockRelease(XactSLRULock);
726 }
#define XactCtl
Definition: clog.c:89
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:614
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:738

◆ CheckPointCLOG()

void CheckPointCLOG ( void  )

Definition at line 818 of file clog.c.

References SimpleLruWriteAll(), and XactCtl.

Referenced by CheckPointGuts().

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

◆ clog_redo()

void clog_redo ( XLogReaderState record)

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

987 {
988  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
989 
990  /* Backup blocks are not used in clog records */
991  Assert(!XLogRecHasAnyBlockRefs(record));
992 
993  if (info == CLOG_ZEROPAGE)
994  {
995  int pageno;
996  int slotno;
997 
998  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
999 
1000  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
1001 
1002  slotno = ZeroCLOGPage(pageno, false);
1003  SimpleLruWritePage(XactCtl, slotno);
1004  Assert(!XactCtl->shared->page_dirty[slotno]);
1005 
1006  LWLockRelease(XactSLRULock);
1007  }
1008  else if (info == CLOG_TRUNCATE)
1009  {
1010  xl_clog_truncate xlrec;
1011 
1012  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
1013 
1015 
1017  }
1018  else
1019  elog(PANIC, "clog_redo: unknown op code %u", info);
1020 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1226
#define XactCtl
Definition: clog.c:89
unsigned char uint8
Definition: c.h:439
#define PANIC
Definition: elog.h:50
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define CLOG_ZEROPAGE
Definition: clog.h:56
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:328
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:614
int pageno
Definition: clog.h:34
#define CLOG_TRUNCATE
Definition: clog.h:57
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:315
TransactionId oldestXact
Definition: clog.h:35
#define Assert(condition)
Definition: c.h:804
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:738
#define elog(elevel,...)
Definition: elog.h:232
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:322

◆ CLOGPagePrecedes()

static bool CLOGPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 934 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

935 {
936  TransactionId xid1;
937  TransactionId xid2;
938 
939  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
940  xid1 += FirstNormalTransactionId + 1;
941  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
942  xid2 += FirstNormalTransactionId + 1;
943 
944  return (TransactionIdPrecedes(xid1, xid2) &&
945  TransactionIdPrecedes(xid1, xid2 + CLOG_XACTS_PER_PAGE - 1));
946 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:62
uint32 TransactionId
Definition: c.h:587
#define FirstNormalTransactionId
Definition: transam.h:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300

◆ CLOGShmemBuffers()

Size CLOGShmemBuffers ( void  )

Definition at line 681 of file clog.c.

References Max, Min, and NBuffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

682 {
683  return Min(128, Max(4, NBuffers / 512));
684 }
#define Min(x, y)
Definition: c.h:986
#define Max(x, y)
Definition: c.h:980
int NBuffers
Definition: globals.c:135

◆ CLOGShmemInit()

void CLOGShmemInit ( void  )

Definition at line 696 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

697 {
698  XactCtl->PagePrecedes = CLOGPagePrecedes;
700  XactSLRULock, "pg_xact", LWTRANCHE_XACT_BUFFER,
703 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:62
#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:187
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:72
static bool CLOGPagePrecedes(int page1, int page2)
Definition: clog.c:934
Size CLOGShmemBuffers(void)
Definition: clog.c:681
#define SlruPagePrecedesUnitTests(ctl, per_page)
Definition: slru.h:156

◆ CLOGShmemSize()

Size CLOGShmemSize ( void  )

Definition at line 690 of file clog.c.

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

Referenced by CalculateShmemSize().

691 {
693 }
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:156
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:72
Size CLOGShmemBuffers(void)
Definition: clog.c:681

◆ clogsyncfiletag()

int clogsyncfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1026 of file clog.c.

References SlruSyncFileTag(), and XactCtl.

1027 {
1028  return SlruSyncFileTag(XactCtl, ftag, path);
1029 }
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
Definition: slru.c:1593
#define XactCtl
Definition: clog.c:89

◆ ExtendCLOG()

void ExtendCLOG ( TransactionId  newestXact)

Definition at line 840 of file clog.c.

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

Referenced by GetNewTransactionId().

841 {
842  int pageno;
843 
844  /*
845  * No work except at first XID of a page. But beware: just after
846  * wraparound, the first XID of page zero is FirstNormalTransactionId.
847  */
848  if (TransactionIdToPgIndex(newestXact) != 0 &&
850  return;
851 
852  pageno = TransactionIdToPage(newestXact);
853 
854  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
855 
856  /* Zero the page and make an XLOG entry about it */
857  ZeroCLOGPage(pageno, true);
858 
859  LWLockRelease(XactSLRULock);
860 }
#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:1803
#define FirstNormalTransactionId
Definition: transam.h:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
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 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:804
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 755 of file clog.c.

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

Referenced by StartupXLOG().

756 {
758  int pageno = TransactionIdToPage(xid);
759 
760  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
761 
762  /*
763  * Initialize our idea of the latest page number.
764  */
765  XactCtl->shared->latest_page_number = pageno;
766 
767  LWLockRelease(XactSLRULock);
768 }
#define TransactionIdToPage(xid)
Definition: clog.c:65
uint32 TransactionId
Definition: c.h:587
#define XactCtl
Definition: clog.c:89
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199

◆ 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  /*
455  * Ensure that this proc is not a member of any clog group that
456  * needs an XID status update.
457  */
458  proc->clogGroupMember = false;
460  return false;
461  }
462 
463  pg_atomic_write_u32(&proc->clogGroupNext, nextidx);
464 
466  &nextidx,
467  (uint32) proc->pgprocno))
468  break;
469  }
470 
471  /*
472  * If the list was not empty, the leader will update the status of our
473  * XID. It is impossible to have followers without a leader because the
474  * first process that has added itself to the list will always have
475  * nextidx as INVALID_PGPROCNO.
476  */
477  if (nextidx != INVALID_PGPROCNO)
478  {
479  int extraWaits = 0;
480 
481  /* Sleep until the leader updates our XID status. */
483  for (;;)
484  {
485  /* acts as a read barrier */
486  PGSemaphoreLock(proc->sem);
487  if (!proc->clogGroupMember)
488  break;
489  extraWaits++;
490  }
492 
494 
495  /* Fix semaphore count for any absorbed wakeups */
496  while (extraWaits-- > 0)
497  PGSemaphoreUnlock(proc->sem);
498  return true;
499  }
500 
501  /* We are the leader. Acquire the lock on behalf of everyone. */
502  LWLockAcquire(XactSLRULock, LW_EXCLUSIVE);
503 
504  /*
505  * Now that we've got the lock, clear the list of processes waiting for
506  * group XID status update, saving a pointer to the head of the list.
507  * Trying to pop elements one at a time could lead to an ABA problem.
508  */
509  nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst,
511 
512  /* Remember head of list so we can perform wakeups after dropping lock. */
513  wakeidx = nextidx;
514 
515  /* Walk the list and update the status of all XIDs. */
516  while (nextidx != INVALID_PGPROCNO)
517  {
518  PGPROC *proc = &ProcGlobal->allProcs[nextidx];
519 
520  /*
521  * Transactions with more than THRESHOLD_SUBTRANS_CLOG_OPT sub-XIDs
522  * should not use group XID status update mechanism.
523  */
525 
527  proc->subxidStatus.count,
528  proc->subxids.xids,
530  proc->clogGroupMemberLsn,
531  proc->clogGroupMemberPage);
532 
533  /* Move to next proc in list. */
534  nextidx = pg_atomic_read_u32(&proc->clogGroupNext);
535  }
536 
537  /* We're done with the lock now. */
538  LWLockRelease(XactSLRULock);
539 
540  /*
541  * Now that we've released the lock, go back and wake everybody up. We
542  * don't do this under the lock so as to keep lock hold times to a
543  * minimum.
544  */
545  while (wakeidx != INVALID_PGPROCNO)
546  {
547  PGPROC *proc = &ProcGlobal->allProcs[wakeidx];
548 
549  wakeidx = pg_atomic_read_u32(&proc->clogGroupNext);
551 
552  /* ensure all previous writes are visible before follower continues. */
554 
555  proc->clogGroupMember = false;
556 
557  if (proc != MyProc)
558  PGSemaphoreUnlock(proc->sem);
559  }
560 
561  return true;
562 }
XidStatus clogGroupMemberXidStatus
Definition: proc.h:232
static void pgstat_report_wait_end(void)
Definition: wait_event.h:278
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:340
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:236
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:68
PROC_HDR * ProcGlobal
Definition: proc.c:80
pg_atomic_uint32 clogGroupNext
Definition: proc.h:230
XidCacheStatus subxidStatus
Definition: proc.h:210
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
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:234
TransactionId clogGroupMemberXid
Definition: proc.h:231
unsigned int uint32
Definition: c.h:441
struct XidCache subxids
Definition: proc.h:212
#define INVALID_PGPROCNO
Definition: proc.h:80
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:262
Definition: proc.h:315
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:48
#define Assert(condition)
Definition: c.h:804
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1199
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:320
uint8 count
Definition: proc.h:41
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:348
int pgprocno
Definition: proc.h:150
bool clogGroupMember
Definition: proc.h:229
#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:318
#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:127
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
Definition: proc.h:121
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 639 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().

640 {
641  int pageno = TransactionIdToPage(xid);
642  int byteno = TransactionIdToByte(xid);
643  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
644  int slotno;
645  int lsnindex;
646  char *byteptr;
648 
649  /* lock is acquired by SimpleLruReadPage_ReadOnly */
650 
651  slotno = SimpleLruReadPage_ReadOnly(XactCtl, pageno, xid);
652  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
653 
654  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
655 
656  lsnindex = GetLSNIndex(slotno, xid);
657  *lsn = XactCtl->shared->group_lsn[lsnindex];
658 
659  LWLockRelease(XactSLRULock);
660 
661  return status;
662 }
#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:1803
#define CLOG_BITS_PER_XACT
Definition: clog.c:60
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:495
#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:587
static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:414
PGPROC * MyProc
Definition: proc.c:68
XidCacheStatus subxidStatus
Definition: proc.h:210
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1803
#define StaticAssertStmt(condition, errmessage)
Definition: c.h:918
#define THRESHOLD_SUBTRANS_CLOG_OPT
Definition: clog.c:82
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1370
struct XidCache subxids
Definition: proc.h:212
#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:1199
uint8 count
Definition: proc.h:41
TransactionId xid
Definition: proc.h:133
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:1937
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:28
static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)
Definition: clog.c:570
#define XactCtl
Definition: clog.c:89
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:395
#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:804
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 570 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().

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

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

◆ TruncateCLOG()

void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 879 of file clog.c.

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

Referenced by vac_truncate_clog().

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

◆ WriteTruncateXlogRec()

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

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

968 {
969  XLogRecPtr recptr;
970  xl_clog_truncate xlrec;
971 
972  xlrec.pageno = pageno;
973  xlrec.oldestXact = oldestXact;
974  xlrec.oldestXactDb = oldestXactDb;
975 
976  XLogBeginInsert();
977  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
978  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
979  XLogFlush(recptr);
980 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2887
int pageno
Definition: clog.h:34
#define CLOG_TRUNCATE
Definition: clog.h:57
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:340
TransactionId oldestXact
Definition: clog.h:35
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXactDb
Definition: clog.h:36
void XLogBeginInsert(void)
Definition: xloginsert.c:135

◆ WriteZeroPageXlogRec()

static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 953 of file clog.c.

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

Referenced by ZeroCLOGPage().

954 {
955  XLogBeginInsert();
956  XLogRegisterData((char *) (&pageno), sizeof(int));
957  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
958 }
#define CLOG_ZEROPAGE
Definition: clog.h:56
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
void XLogBeginInsert(void)
Definition: xloginsert.c:135

◆ ZeroCLOGPage()

static int ZeroCLOGPage ( int  pageno,
bool  writeXlog 
)
static

Definition at line 738 of file clog.c.

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

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

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

Variable Documentation

◆ XactCtlData

SlruCtlData XactCtlData
static

Definition at line 87 of file clog.c.