PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 "utils/guc_hooks.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 CLOG_MAX_ALLOWED_BUFFERS
 
#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 int64 TransactionIdToPage (TransactionId xid)
 
static int ZeroCLOGPage (int64 pageno, bool writeXlog)
 
static bool CLOGPagePrecedes (int64 page1, int64 page2)
 
static void WriteZeroPageXlogRec (int64 pageno)
 
static void WriteTruncateXlogRec (int64 pageno, TransactionId oldestXact, Oid oldestXactDb)
 
static void TransactionIdSetPageStatus (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 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, int64 pageno)
 
static void TransactionIdSetPageStatusInternal (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 pageno)
 
void TransactionIdSetTreeStatus (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
 
XidStatus TransactionIdGetStatus (TransactionId xid, XLogRecPtr *lsn)
 
static int CLOGShmemBuffers (void)
 
Size CLOGShmemSize (void)
 
void CLOGShmemInit (void)
 
bool check_transaction_buffers (int *newval, void **extra, GucSource source)
 
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 62 of file clog.c.

◆ CLOG_LSNS_PER_PAGE

#define CLOG_LSNS_PER_PAGE   (CLOG_XACTS_PER_PAGE / CLOG_XACTS_PER_LSN_GROUP)

Definition at line 93 of file clog.c.

◆ CLOG_MAX_ALLOWED_BUFFERS

#define CLOG_MAX_ALLOWED_BUFFERS
Value:
#define Min(x, y)
Definition: c.h:1009
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:64
#define SLRU_MAX_ALLOWED_BUFFERS
Definition: slru.h:24
#define MaxTransactionId
Definition: transam.h:35

Definition at line 72 of file clog.c.

◆ CLOG_XACT_BITMASK

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

Definition at line 65 of file clog.c.

◆ CLOG_XACTS_PER_BYTE

#define CLOG_XACTS_PER_BYTE   4

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

◆ CLOG_XACTS_PER_PAGE

#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)

Definition at line 64 of file clog.c.

◆ GetLSNIndex

#define GetLSNIndex (   slotno,
  xid 
)
Value:
((slotno) * CLOG_LSNS_PER_PAGE + \
uint32 TransactionId
Definition: c.h:657
#define CLOG_XACTS_PER_LSN_GROUP
Definition: clog.c:92
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:93

Definition at line 95 of file clog.c.

◆ THRESHOLD_SUBTRANS_CLOG_OPT

#define THRESHOLD_SUBTRANS_CLOG_OPT   5

Definition at line 103 of file clog.c.

◆ TransactionIdToBIndex

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

Definition at line 89 of file clog.c.

◆ TransactionIdToByte

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

Definition at line 88 of file clog.c.

◆ TransactionIdToPgIndex

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

Definition at line 87 of file clog.c.

◆ XactCtl

#define XactCtl   (&XactCtlData)

Definition at line 110 of file clog.c.

Function Documentation

◆ BootStrapCLOG()

void BootStrapCLOG ( void  )

Definition at line 833 of file clog.c.

834 {
835  int slotno;
836  LWLock *lock = SimpleLruGetBankLock(XactCtl, 0);
837 
839 
840  /* Create and zero the first page of the commit log */
841  slotno = ZeroCLOGPage(0, false);
842 
843  /* Make sure it's written out */
844  SimpleLruWritePage(XactCtl, slotno);
845  Assert(!XactCtl->shared->page_dirty[slotno]);
846 
847  LWLockRelease(lock);
848 }
#define Assert(condition)
Definition: c.h:863
static int ZeroCLOGPage(int64 pageno, bool writeXlog)
Definition: clog.c:860
#define XactCtl
Definition: clog.c:110
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_EXCLUSIVE
Definition: lwlock.h:114
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:732
static LWLock * SimpleLruGetBankLock(SlruCtl ctl, int64 pageno)
Definition: slru.h:178
Definition: lwlock.h:42

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

Referenced by BootStrapXLOG().

◆ check_transaction_buffers()

bool check_transaction_buffers ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 821 of file clog.c.

822 {
823  return check_slru_buffers("transaction_buffers", newval);
824 }
#define newval
bool check_slru_buffers(const char *name, int *newval)
Definition: slru.c:355

References check_slru_buffers(), and newval.

◆ CheckPointCLOG()

void CheckPointCLOG ( void  )

Definition at line 937 of file clog.c.

938 {
939  /*
940  * Write dirty CLOG pages to disk. This may result in sync requests
941  * queued for later handling by ProcessSyncRequests(), as part of the
942  * checkpoint.
943  */
944  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
945  SimpleLruWriteAll(XactCtl, true);
946  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
947 }
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1322

References SimpleLruWriteAll(), and XactCtl.

Referenced by CheckPointGuts().

◆ clog_redo()

void clog_redo ( XLogReaderState record)

Definition at line 1107 of file clog.c.

1108 {
1109  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1110 
1111  /* Backup blocks are not used in clog records */
1112  Assert(!XLogRecHasAnyBlockRefs(record));
1113 
1114  if (info == CLOG_ZEROPAGE)
1115  {
1116  int64 pageno;
1117  int slotno;
1118  LWLock *lock;
1119 
1120  memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
1121 
1122  lock = SimpleLruGetBankLock(XactCtl, pageno);
1123  LWLockAcquire(lock, LW_EXCLUSIVE);
1124 
1125  slotno = ZeroCLOGPage(pageno, false);
1126  SimpleLruWritePage(XactCtl, slotno);
1127  Assert(!XactCtl->shared->page_dirty[slotno]);
1128 
1129  LWLockRelease(lock);
1130  }
1131  else if (info == CLOG_TRUNCATE)
1132  {
1133  xl_clog_truncate xlrec;
1134 
1135  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
1136 
1138 
1140  }
1141  else
1142  elog(PANIC, "clog_redo: unknown op code %u", info);
1143 }
unsigned char uint8
Definition: c.h:516
#define CLOG_ZEROPAGE
Definition: clog.h:55
#define CLOG_TRUNCATE
Definition: clog.h:56
#define PANIC
Definition: elog.h:42
#define elog(elevel,...)
Definition: elog.h:225
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
Definition: slru.c:1408
int64 pageno
Definition: clog.h:34
TransactionId oldestXact
Definition: clog.h:35
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:355
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

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

◆ CLOGPagePrecedes()

static bool CLOGPagePrecedes ( int64  page1,
int64  page2 
)
static

Definition at line 1055 of file clog.c.

1056 {
1057  TransactionId xid1;
1058  TransactionId xid2;
1059 
1060  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
1061  xid1 += FirstNormalTransactionId + 1;
1062  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
1063  xid2 += FirstNormalTransactionId + 1;
1064 
1065  return (TransactionIdPrecedes(xid1, xid2) &&
1066  TransactionIdPrecedes(xid1, xid2 + CLOG_XACTS_PER_PAGE - 1));
1067 }
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280
#define FirstNormalTransactionId
Definition: transam.h:34

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

◆ CLOGShmemBuffers()

static int CLOGShmemBuffers ( void  )
static

Definition at line 768 of file clog.c.

769 {
770  /* auto-tune based on shared buffers */
771  if (transaction_buffers == 0)
772  return SimpleLruAutotuneBuffers(512, 1024);
773 
775 }
#define Max(x, y)
Definition: c.h:1003
#define CLOG_MAX_ALLOWED_BUFFERS
Definition: clog.c:72
int transaction_buffers
Definition: globals.c:166
int SimpleLruAutotuneBuffers(int divisor, int max)
Definition: slru.c:232

References CLOG_MAX_ALLOWED_BUFFERS, Max, Min, SimpleLruAutotuneBuffers(), and transaction_buffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

◆ CLOGShmemInit()

void CLOGShmemInit ( void  )

Definition at line 787 of file clog.c.

788 {
789  /* If auto-tuning is requested, now is the time to do it */
790  if (transaction_buffers == 0)
791  {
792  char buf[32];
793 
794  snprintf(buf, sizeof(buf), "%d", CLOGShmemBuffers());
795  SetConfigOption("transaction_buffers", buf, PGC_POSTMASTER,
797 
798  /*
799  * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT.
800  * However, if the DBA explicitly set transaction_buffers = 0 in the
801  * config file, then PGC_S_DYNAMIC_DEFAULT will fail to override that
802  * and we must force the matter with PGC_S_OVERRIDE.
803  */
804  if (transaction_buffers == 0) /* failed to apply it? */
805  SetConfigOption("transaction_buffers", buf, PGC_POSTMASTER,
807  }
809 
810  XactCtl->PagePrecedes = CLOGPagePrecedes;
812  "pg_xact", LWTRANCHE_XACT_BUFFER,
815 }
static int CLOGShmemBuffers(void)
Definition: clog.c:768
static bool CLOGPagePrecedes(int64 page1, int64 page2)
Definition: clog.c:1055
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4332
@ PGC_S_DYNAMIC_DEFAULT
Definition: guc.h:110
@ PGC_S_OVERRIDE
Definition: guc.h:119
@ PGC_POSTMASTER
Definition: guc.h:70
@ LWTRANCHE_XACT_BUFFER
Definition: lwlock.h:179
@ LWTRANCHE_XACT_SLRU
Definition: lwlock.h:216
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:238
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, const char *subdir, int buffer_tranche_id, int bank_tranche_id, SyncRequestHandler sync_handler, bool long_segment_names)
Definition: slru.c:252
#define SlruPagePrecedesUnitTests(ctl, per_page)
Definition: slru.h:202
@ SYNC_HANDLER_CLOG
Definition: sync.h:38

References Assert, buf, CLOG_LSNS_PER_PAGE, CLOG_XACTS_PER_PAGE, CLOGPagePrecedes(), CLOGShmemBuffers(), LWTRANCHE_XACT_BUFFER, LWTRANCHE_XACT_SLRU, PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT, PGC_S_OVERRIDE, SetConfigOption(), SimpleLruInit(), SlruPagePrecedesUnitTests, snprintf, SYNC_HANDLER_CLOG, transaction_buffers, and XactCtl.

Referenced by CreateOrAttachShmemStructs().

◆ CLOGShmemSize()

Size CLOGShmemSize ( void  )

Definition at line 781 of file clog.c.

782 {
784 }
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:199

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

Referenced by CalculateShmemSize().

◆ clogsyncfiletag()

int clogsyncfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1149 of file clog.c.

1150 {
1151  return SlruSyncFileTag(XactCtl, ftag, path);
1152 }
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
Definition: slru.c:1831

References SlruSyncFileTag(), and XactCtl.

◆ ExtendCLOG()

void ExtendCLOG ( TransactionId  newestXact)

Definition at line 959 of file clog.c.

960 {
961  int64 pageno;
962  LWLock *lock;
963 
964  /*
965  * No work except at first XID of a page. But beware: just after
966  * wraparound, the first XID of page zero is FirstNormalTransactionId.
967  */
968  if (TransactionIdToPgIndex(newestXact) != 0 &&
970  return;
971 
972  pageno = TransactionIdToPage(newestXact);
973  lock = SimpleLruGetBankLock(XactCtl, pageno);
974 
976 
977  /* Zero the page and make an XLOG entry about it */
978  ZeroCLOGPage(pageno, true);
979 
980  LWLockRelease(lock);
981 }
static int64 TransactionIdToPage(TransactionId xid)
Definition: clog.c:82
#define TransactionIdToPgIndex(xid)
Definition: clog.c:87
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43

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

Referenced by GetNewTransactionId().

◆ set_status_by_pages()

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

Definition at line 257 of file clog.c.

259 {
260  int64 pageno = TransactionIdToPage(subxids[0]);
261  int offset = 0;
262  int i = 0;
263 
264  Assert(nsubxids > 0); /* else the pageno fetch above is unsafe */
265 
266  while (i < nsubxids)
267  {
268  int num_on_page = 0;
269  int64 nextpageno;
270 
271  do
272  {
273  nextpageno = TransactionIdToPage(subxids[i]);
274  if (nextpageno != pageno)
275  break;
276  num_on_page++;
277  i++;
278  } while (i < nsubxids);
279 
281  num_on_page, subxids + offset,
282  status, lsn, pageno, false);
283  offset = i;
284  pageno = nextpageno;
285  }
286 }
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 pageno, bool all_xact_same_page)
Definition: clog.c:293
int i
Definition: isn.c:72
#define InvalidTransactionId
Definition: transam.h:31

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

Referenced by TransactionIdSetTreeStatus().

◆ StartupCLOG()

void StartupCLOG ( void  )

Definition at line 877 of file clog.c.

878 {
880  int64 pageno = TransactionIdToPage(xid);
881 
882  /*
883  * Initialize our idea of the latest page number.
884  */
885  pg_atomic_write_u64(&XactCtl->shared->latest_page_number, pageno);
886 }
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition: atomics.h:485
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
TransamVariablesData * TransamVariables
Definition: varsup.c:34

References TransamVariablesData::nextXid, pg_atomic_write_u64(), TransactionIdToPage(), TransamVariables, XactCtl, and XidFromFullTransactionId.

Referenced by StartupXLOG().

◆ TransactionGroupUpdateXidStatus()

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

Definition at line 441 of file clog.c.

443 {
444  volatile PROC_HDR *procglobal = ProcGlobal;
445  PGPROC *proc = MyProc;
446  uint32 nextidx;
447  uint32 wakeidx;
448  int64 prevpageno;
449  LWLock *prevlock = NULL;
450 
451  /* We should definitely have an XID whose status needs to be updated. */
453 
454  /*
455  * Prepare to add ourselves to the list of processes needing a group XID
456  * status update.
457  */
458  proc->clogGroupMember = true;
459  proc->clogGroupMemberXid = xid;
460  proc->clogGroupMemberXidStatus = status;
461  proc->clogGroupMemberPage = pageno;
462  proc->clogGroupMemberLsn = lsn;
463 
464  /*
465  * We put ourselves in the queue by writing MyProcNumber to
466  * ProcGlobal->clogGroupFirst. However, if there's already a process
467  * listed there, we compare our pageno with that of that process; if it
468  * differs, we cannot participate in the group, so we return for caller to
469  * update pg_xact in the normal way.
470  *
471  * If we're not the first process in the list, we must follow the leader.
472  * We do this by storing the data we want updated in our PGPROC entry
473  * where the leader can find it, then going to sleep.
474  *
475  * If no process is already in the list, we're the leader; our first step
476  * is to lock the SLRU bank to which our page belongs, then we close out
477  * the group by resetting the list pointer from ProcGlobal->clogGroupFirst
478  * (this lets other processes set up other groups later); finally we do
479  * the SLRU updates, release the SLRU bank lock, and wake up the sleeping
480  * processes.
481  *
482  * If another group starts to update a page in a different SLRU bank, they
483  * can proceed concurrently, since the bank lock they're going to use is
484  * different from ours. If another group starts to update a page in the
485  * same bank as ours, they wait until we release the lock.
486  */
487  nextidx = pg_atomic_read_u32(&procglobal->clogGroupFirst);
488 
489  while (true)
490  {
491  /*
492  * Add the proc to list, if the clog page where we need to update the
493  * current transaction status is same as group leader's clog page.
494  *
495  * There is a race condition here, which is that after doing the below
496  * check and before adding this proc's clog update to a group, the
497  * group leader might have already finished the group update for this
498  * page and becomes group leader of another group, updating a
499  * different page. This will lead to a situation where a single group
500  * can have different clog page updates. This isn't likely and will
501  * still work, just less efficiently -- we handle this case by
502  * switching to a different bank lock in the loop below.
503  */
504  if (nextidx != INVALID_PROC_NUMBER &&
505  GetPGProcByNumber(nextidx)->clogGroupMemberPage != proc->clogGroupMemberPage)
506  {
507  /*
508  * Ensure that this proc is not a member of any clog group that
509  * needs an XID status update.
510  */
511  proc->clogGroupMember = false;
513  return false;
514  }
515 
516  pg_atomic_write_u32(&proc->clogGroupNext, nextidx);
517 
519  &nextidx,
520  (uint32) MyProcNumber))
521  break;
522  }
523 
524  /*
525  * If the list was not empty, the leader will update the status of our
526  * XID. It is impossible to have followers without a leader because the
527  * first process that has added itself to the list will always have
528  * nextidx as INVALID_PROC_NUMBER.
529  */
530  if (nextidx != INVALID_PROC_NUMBER)
531  {
532  int extraWaits = 0;
533 
534  /* Sleep until the leader updates our XID status. */
535  pgstat_report_wait_start(WAIT_EVENT_XACT_GROUP_UPDATE);
536  for (;;)
537  {
538  /* acts as a read barrier */
539  PGSemaphoreLock(proc->sem);
540  if (!proc->clogGroupMember)
541  break;
542  extraWaits++;
543  }
545 
547 
548  /* Fix semaphore count for any absorbed wakeups */
549  while (extraWaits-- > 0)
550  PGSemaphoreUnlock(proc->sem);
551  return true;
552  }
553 
554  /*
555  * By here, we know we're the leader process. Acquire the SLRU bank lock
556  * that corresponds to the page we originally wanted to modify.
557  */
558  prevpageno = proc->clogGroupMemberPage;
559  prevlock = SimpleLruGetBankLock(XactCtl, prevpageno);
560  LWLockAcquire(prevlock, LW_EXCLUSIVE);
561 
562  /*
563  * Now that we've got the lock, clear the list of processes waiting for
564  * group XID status update, saving a pointer to the head of the list.
565  * (Trying to pop elements one at a time could lead to an ABA problem.)
566  *
567  * At this point, any processes trying to do this would create a separate
568  * group.
569  */
570  nextidx = pg_atomic_exchange_u32(&procglobal->clogGroupFirst,
572 
573  /* Remember head of list so we can perform wakeups after dropping lock. */
574  wakeidx = nextidx;
575 
576  /* Walk the list and update the status of all XIDs. */
577  while (nextidx != INVALID_PROC_NUMBER)
578  {
579  PGPROC *nextproc = &ProcGlobal->allProcs[nextidx];
580  int64 thispageno = nextproc->clogGroupMemberPage;
581 
582  /*
583  * If the page to update belongs to a different bank than the previous
584  * one, exchange bank lock to the new one. This should be quite rare,
585  * as described above.
586  *
587  * (We could try to optimize this by waking up the processes for which
588  * we have already updated the status while we exchange the lock, but
589  * the code doesn't do that at present. I think it'd require
590  * additional bookkeeping, making the common path slower in order to
591  * improve an infrequent case.)
592  */
593  if (thispageno != prevpageno)
594  {
595  LWLock *lock = SimpleLruGetBankLock(XactCtl, thispageno);
596 
597  if (prevlock != lock)
598  {
599  LWLockRelease(prevlock);
601  }
602  prevlock = lock;
603  prevpageno = thispageno;
604  }
605 
606  /*
607  * Transactions with more than THRESHOLD_SUBTRANS_CLOG_OPT sub-XIDs
608  * should not use group XID status update mechanism.
609  */
611 
613  nextproc->subxidStatus.count,
614  nextproc->subxids.xids,
615  nextproc->clogGroupMemberXidStatus,
616  nextproc->clogGroupMemberLsn,
617  nextproc->clogGroupMemberPage);
618 
619  /* Move to next proc in list. */
620  nextidx = pg_atomic_read_u32(&nextproc->clogGroupNext);
621  }
622 
623  /* We're done with the lock now. */
624  if (prevlock != NULL)
625  LWLockRelease(prevlock);
626 
627  /*
628  * Now that we've released the lock, go back and wake everybody up. We
629  * don't do this under the lock so as to keep lock hold times to a
630  * minimum.
631  *
632  * (Perhaps we could do this in two passes, the first setting
633  * clogGroupNext to invalid while saving the semaphores to an array, then
634  * a single write barrier, then another pass unlocking the semaphores.)
635  */
636  while (wakeidx != INVALID_PROC_NUMBER)
637  {
638  PGPROC *wakeproc = &ProcGlobal->allProcs[wakeidx];
639 
640  wakeidx = pg_atomic_read_u32(&wakeproc->clogGroupNext);
642 
643  /* ensure all previous writes are visible before follower continues. */
645 
646  wakeproc->clogGroupMember = false;
647 
648  if (wakeproc != MyProc)
649  PGSemaphoreUnlock(wakeproc->sem);
650  }
651 
652  return true;
653 }
static bool pg_atomic_compare_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
Definition: atomics.h:349
#define pg_write_barrier()
Definition: atomics.h:157
static void pg_atomic_write_u32(volatile pg_atomic_uint32 *ptr, uint32 val)
Definition: atomics.h:276
static uint32 pg_atomic_read_u32(volatile pg_atomic_uint32 *ptr)
Definition: atomics.h:239
static uint32 pg_atomic_exchange_u32(volatile pg_atomic_uint32 *ptr, uint32 newval)
Definition: atomics.h:330
unsigned int uint32
Definition: c.h:518
#define THRESHOLD_SUBTRANS_CLOG_OPT
Definition: clog.c:103
static void TransactionIdSetPageStatusInternal(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int64 pageno)
Definition: clog.c:364
ProcNumber MyProcNumber
Definition: globals.c:89
void PGSemaphoreUnlock(PGSemaphore sema)
Definition: posix_sema.c:339
void PGSemaphoreLock(PGSemaphore sema)
Definition: posix_sema.c:319
#define GetPGProcByNumber(n)
Definition: proc.h:436
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
PGPROC * MyProc
Definition: proc.c:66
PROC_HDR * ProcGlobal
Definition: proc.c:78
Definition: proc.h:162
XLogRecPtr clogGroupMemberLsn
Definition: proc.h:289
TransactionId clogGroupMemberXid
Definition: proc.h:284
int64 clogGroupMemberPage
Definition: proc.h:287
bool clogGroupMember
Definition: proc.h:282
pg_atomic_uint32 clogGroupNext
Definition: proc.h:283
XidStatus clogGroupMemberXidStatus
Definition: proc.h:285
XidCacheStatus subxidStatus
Definition: proc.h:263
struct XidCache subxids
Definition: proc.h:265
PGSemaphore sem
Definition: proc.h:166
Definition: proc.h:382
PGPROC * allProcs
Definition: proc.h:384
pg_atomic_uint32 clogGroupFirst
Definition: proc.h:414
uint8 count
Definition: proc.h:44
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS]
Definition: proc.h:51
#define TransactionIdIsValid(xid)
Definition: transam.h:41
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:85
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101

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

Referenced by TransactionIdSetPageStatus().

◆ TransactionIdGetStatus()

XidStatus TransactionIdGetStatus ( TransactionId  xid,
XLogRecPtr lsn 
)

Definition at line 735 of file clog.c.

736 {
737  int64 pageno = TransactionIdToPage(xid);
738  int byteno = TransactionIdToByte(xid);
739  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
740  int slotno;
741  int lsnindex;
742  char *byteptr;
743  XidStatus status;
744 
745  /* lock is acquired by SimpleLruReadPage_ReadOnly */
746 
747  slotno = SimpleLruReadPage_ReadOnly(XactCtl, pageno, xid);
748  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
749 
750  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
751 
752  lsnindex = GetLSNIndex(slotno, xid);
753  *lsn = XactCtl->shared->group_lsn[lsnindex];
754 
756 
757  return status;
758 }
#define CLOG_XACT_BITMASK
Definition: clog.c:65
#define TransactionIdToBIndex(xid)
Definition: clog.c:89
#define CLOG_BITS_PER_XACT
Definition: clog.c:62
#define TransactionIdToByte(xid)
Definition: clog.c:88
#define GetLSNIndex(slotno, xid)
Definition: clog.c:95
int XidStatus
Definition: clog.h:25
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, TransactionId xid)
Definition: slru.c:605

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

Referenced by TransactionIdGetCommitLSN(), and TransactionLogFetch().

◆ TransactionIdSetPageStatus()

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

Definition at line 293 of file clog.c.

297 {
298  LWLock *lock;
299 
300  /* Can't use group update when PGPROC overflows. */
302  "group clog threshold less than PGPROC cached subxids");
303 
304  /* Get the SLRU bank lock for the page we are going to access. */
305  lock = SimpleLruGetBankLock(XactCtl, pageno);
306 
307  /*
308  * When there is contention on the SLRU bank lock we need, we try to group
309  * multiple updates; a single leader process will perform transaction
310  * status updates for multiple backends so that the number of times the
311  * bank lock needs to be acquired is reduced.
312  *
313  * For this optimization to be safe, the XID and subxids in MyProc must be
314  * the same as the ones for which we're setting the status. Check that
315  * this is the case.
316  *
317  * For this optimization to be efficient, we shouldn't have too many
318  * sub-XIDs and all of the XIDs for which we're adjusting clog should be
319  * on the same page. Check those conditions, too.
320  */
321  if (all_xact_same_page && xid == MyProc->xid &&
322  nsubxids <= THRESHOLD_SUBTRANS_CLOG_OPT &&
323  nsubxids == MyProc->subxidStatus.count &&
324  (nsubxids == 0 ||
325  memcmp(subxids, MyProc->subxids.xids,
326  nsubxids * sizeof(TransactionId)) == 0))
327  {
328  /*
329  * If we can immediately acquire the lock, we update the status of our
330  * own XID and release the lock. If not, try use group XID update. If
331  * that doesn't work out, fall back to waiting for the lock to perform
332  * an update for this transaction only.
333  */
335  {
336  /* Got the lock without waiting! Do the update. */
337  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
338  lsn, pageno);
339  LWLockRelease(lock);
340  return;
341  }
342  else if (TransactionGroupUpdateXidStatus(xid, status, lsn, pageno))
343  {
344  /* Group update mechanism has done the work. */
345  return;
346  }
347 
348  /* Fall through only if update isn't done yet. */
349  }
350 
351  /* Group update not applicable, or couldn't accept this page number. */
353  TransactionIdSetPageStatusInternal(xid, nsubxids, subxids, status,
354  lsn, pageno);
355  LWLockRelease(lock);
356 }
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:941
static bool TransactionGroupUpdateXidStatus(TransactionId xid, XidStatus status, XLogRecPtr lsn, int64 pageno)
Definition: clog.c:441
bool LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1339
#define PGPROC_MAX_CACHED_SUBXIDS
Definition: proc.h:39
TransactionId xid
Definition: proc.h:172

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

Referenced by set_status_by_pages(), and TransactionIdSetTreeStatus().

◆ TransactionIdSetPageStatusInternal()

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

Definition at line 364 of file clog.c.

367 {
368  int slotno;
369  int i;
370 
372  status == TRANSACTION_STATUS_ABORTED ||
375  LW_EXCLUSIVE));
376 
377  /*
378  * If we're doing an async commit (ie, lsn is valid), then we must wait
379  * for any active write on the page slot to complete. Otherwise our
380  * update could reach disk in that write, which will not do since we
381  * mustn't let it reach disk until we've done the appropriate WAL flush.
382  * But when lsn is invalid, it's OK to scribble on a page while it is
383  * write-busy, since we don't care if the update reaches disk sooner than
384  * we think.
385  */
386  slotno = SimpleLruReadPage(XactCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
387 
388  /*
389  * Set the main transaction id, if any.
390  *
391  * If we update more than one xid on this page while it is being written
392  * out, we might find that some of the bits go to disk and others don't.
393  * If we are updating commits on the page with the top-level xid that
394  * could break atomicity, so we subcommit the subxids first before we mark
395  * the top-level commit.
396  */
397  if (TransactionIdIsValid(xid))
398  {
399  /* Subtransactions first, if needed ... */
400  if (status == TRANSACTION_STATUS_COMMITTED)
401  {
402  for (i = 0; i < nsubxids; i++)
403  {
404  Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
405  TransactionIdSetStatusBit(subxids[i],
407  lsn, slotno);
408  }
409  }
410 
411  /* ... then the main transaction */
412  TransactionIdSetStatusBit(xid, status, lsn, slotno);
413  }
414 
415  /* Set the subtransactions */
416  for (i = 0; i < nsubxids; i++)
417  {
418  Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
419  TransactionIdSetStatusBit(subxids[i], status, lsn, slotno);
420  }
421 
422  XactCtl->shared->page_dirty[slotno] = true;
423 }
static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)
Definition: clog.c:661
#define TRANSACTION_STATUS_ABORTED
Definition: clog.h:29
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:30
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:28
bool LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1937
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
Definition: slru.c:502
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29

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

Referenced by TransactionGroupUpdateXidStatus(), and TransactionIdSetPageStatus().

◆ TransactionIdSetStatusBit()

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

Definition at line 661 of file clog.c.

662 {
663  int byteno = TransactionIdToByte(xid);
664  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
665  char *byteptr;
666  char byteval;
667  char curval;
668 
669  Assert(XactCtl->shared->page_number[slotno] == TransactionIdToPage(xid));
671  XactCtl->shared->page_number[slotno]),
672  LW_EXCLUSIVE));
673 
674  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
675  curval = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
676 
677  /*
678  * When replaying transactions during recovery we still need to perform
679  * the two phases of subcommit and then commit. However, some transactions
680  * are already correctly marked, so we just treat those as a no-op which
681  * allows us to keep the following Assert as restrictive as possible.
682  */
683  if (InRecovery && status == TRANSACTION_STATUS_SUB_COMMITTED &&
685  return;
686 
687  /*
688  * Current state change should be from 0 or subcommitted to target state
689  * or we should already be there when replaying changes during recovery.
690  */
691  Assert(curval == 0 ||
693  status != TRANSACTION_STATUS_IN_PROGRESS) ||
694  curval == status);
695 
696  /* note this assumes exclusive access to the clog page */
697  byteval = *byteptr;
698  byteval &= ~(((1 << CLOG_BITS_PER_XACT) - 1) << bshift);
699  byteval |= (status << bshift);
700  *byteptr = byteval;
701 
702  /*
703  * Update the group LSN if the transaction completion LSN is higher.
704  *
705  * Note: lsn will be invalid when supplied during InRecovery processing,
706  * so we don't need to do anything special to avoid LSN updates during
707  * recovery. After recovery completes the next clog change will set the
708  * LSN correctly.
709  */
710  if (!XLogRecPtrIsInvalid(lsn))
711  {
712  int lsnindex = GetLSNIndex(slotno, xid);
713 
714  if (XactCtl->shared->group_lsn[lsnindex] < lsn)
715  XactCtl->shared->group_lsn[lsnindex] = lsn;
716  }
717 }
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:27
bool InRecovery
Definition: xlogutils.c:50

References Assert, CLOG_BITS_PER_XACT, CLOG_XACT_BITMASK, GetLSNIndex, InRecovery, LW_EXCLUSIVE, LWLockHeldByMeInMode(), SimpleLruGetBankLock(), TRANSACTION_STATUS_COMMITTED, TRANSACTION_STATUS_IN_PROGRESS, TRANSACTION_STATUS_SUB_COMMITTED, TransactionIdToBIndex, TransactionIdToByte, TransactionIdToPage(), XactCtl, and XLogRecPtrIsInvalid.

Referenced by TransactionIdSetPageStatusInternal().

◆ TransactionIdSetTreeStatus()

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

Definition at line 183 of file clog.c.

185 {
186  int64 pageno = TransactionIdToPage(xid); /* get page of parent */
187  int i;
188 
190  status == TRANSACTION_STATUS_ABORTED);
191 
192  /*
193  * See how many subxids, if any, are on the same page as the parent, if
194  * any.
195  */
196  for (i = 0; i < nsubxids; i++)
197  {
198  if (TransactionIdToPage(subxids[i]) != pageno)
199  break;
200  }
201 
202  /*
203  * Do all items fit on a single page?
204  */
205  if (i == nsubxids)
206  {
207  /*
208  * Set the parent and all subtransactions in a single call
209  */
210  TransactionIdSetPageStatus(xid, nsubxids, subxids, status, lsn,
211  pageno, true);
212  }
213  else
214  {
215  int nsubxids_on_first_page = i;
216 
217  /*
218  * If this is a commit then we care about doing this correctly (i.e.
219  * using the subcommitted intermediate status). By here, we know
220  * we're updating more than one page of clog, so we must mark entries
221  * that are *not* on the first page so that they show as subcommitted
222  * before we then return to update the status to fully committed.
223  *
224  * To avoid touching the first page twice, skip marking subcommitted
225  * for the subxids on that first page.
226  */
227  if (status == TRANSACTION_STATUS_COMMITTED)
228  set_status_by_pages(nsubxids - nsubxids_on_first_page,
229  subxids + nsubxids_on_first_page,
231 
232  /*
233  * Now set the parent and subtransactions on same page as the parent,
234  * if any
235  */
236  pageno = TransactionIdToPage(xid);
237  TransactionIdSetPageStatus(xid, nsubxids_on_first_page, subxids, status,
238  lsn, pageno, false);
239 
240  /*
241  * Now work through the rest of the subxids one clog page at a time,
242  * starting from the second page onwards, like we did above.
243  */
244  set_status_by_pages(nsubxids - nsubxids_on_first_page,
245  subxids + nsubxids_on_first_page,
246  status, lsn);
247  }
248 }
static void set_status_by_pages(int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
Definition: clog.c:257

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

◆ TransactionIdToPage()

static int64 TransactionIdToPage ( TransactionId  xid)
inlinestatic

◆ TrimCLOG()

void TrimCLOG ( void  )

Definition at line 892 of file clog.c.

893 {
895  int64 pageno = TransactionIdToPage(xid);
896  LWLock *lock = SimpleLruGetBankLock(XactCtl, pageno);
897 
899 
900  /*
901  * Zero out the remainder of the current clog page. Under normal
902  * circumstances it should be zeroes already, but it seems at least
903  * theoretically possible that XLOG replay will have settled on a nextXID
904  * value that is less than the last XID actually used and marked by the
905  * previous database lifecycle (since subtransaction commit writes clog
906  * but makes no WAL entry). Let's just be safe. (We need not worry about
907  * pages beyond the current one, since those will be zeroed when first
908  * used. For the same reason, there is no need to do anything when
909  * nextXid is exactly at a page boundary; and it's likely that the
910  * "current" page doesn't exist yet in that case.)
911  */
912  if (TransactionIdToPgIndex(xid) != 0)
913  {
914  int byteno = TransactionIdToByte(xid);
915  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
916  int slotno;
917  char *byteptr;
918 
919  slotno = SimpleLruReadPage(XactCtl, pageno, false, xid);
920  byteptr = XactCtl->shared->page_buffer[slotno] + byteno;
921 
922  /* Zero so-far-unused positions in the current byte */
923  *byteptr &= (1 << bshift) - 1;
924  /* Zero the rest of the page */
925  MemSet(byteptr + 1, 0, BLCKSZ - byteno - 1);
926 
927  XactCtl->shared->page_dirty[slotno] = true;
928  }
929 
930  LWLockRelease(lock);
931 }
#define MemSet(start, val, len)
Definition: c.h:1025

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

Referenced by StartupXLOG().

◆ TruncateCLOG()

void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 1000 of file clog.c.

1001 {
1002  int64 cutoffPage;
1003 
1004  /*
1005  * The cutoff point is the start of the segment containing oldestXact. We
1006  * pass the *page* containing oldestXact to SimpleLruTruncate.
1007  */
1008  cutoffPage = TransactionIdToPage(oldestXact);
1009 
1010  /* Check to see if there's any files that could be removed */
1012  return; /* nothing to remove */
1013 
1014  /*
1015  * Advance oldestClogXid before truncating clog, so concurrent xact status
1016  * lookups can ensure they don't attempt to access truncated-away clog.
1017  *
1018  * It's only necessary to do this if we will actually truncate away clog
1019  * pages.
1020  */
1021  AdvanceOldestClogXid(oldestXact);
1022 
1023  /*
1024  * Write XLOG record and flush XLOG to disk. We record the oldest xid
1025  * we're keeping information about here so we can ensure that it's always
1026  * ahead of clog truncation in case we crash, and so a standby finds out
1027  * the new valid xid before the next checkpoint.
1028  */
1029  WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid);
1030 
1031  /* Now we can remove the old CLOG segment(s) */
1032  SimpleLruTruncate(XactCtl, cutoffPage);
1033 }
static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXact, Oid oldestXactDb)
Definition: clog.c:1088
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1791
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int64 segpage, void *data)
Definition: slru.c:1712

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

Referenced by vac_truncate_clog().

◆ WriteTruncateXlogRec()

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

Definition at line 1088 of file clog.c.

1089 {
1090  XLogRecPtr recptr;
1091  xl_clog_truncate xlrec;
1092 
1093  xlrec.pageno = pageno;
1094  xlrec.oldestXact = oldestXact;
1095  xlrec.oldestXactDb = oldestXactDb;
1096 
1097  XLogBeginInsert();
1098  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
1099  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
1100  XLogFlush(recptr);
1101 }
Oid oldestXactDb
Definition: clog.h:36
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2802
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const char *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149

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

Referenced by TruncateCLOG().

◆ WriteZeroPageXlogRec()

static void WriteZeroPageXlogRec ( int64  pageno)
static

Definition at line 1074 of file clog.c.

1075 {
1076  XLogBeginInsert();
1077  XLogRegisterData((char *) (&pageno), sizeof(pageno));
1078  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
1079 }

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

Referenced by ZeroCLOGPage().

◆ ZeroCLOGPage()

static int ZeroCLOGPage ( int64  pageno,
bool  writeXlog 
)
static

Definition at line 860 of file clog.c.

861 {
862  int slotno;
863 
864  slotno = SimpleLruZeroPage(XactCtl, pageno);
865 
866  if (writeXlog)
867  WriteZeroPageXlogRec(pageno);
868 
869  return slotno;
870 }
static void WriteZeroPageXlogRec(int64 pageno)
Definition: clog.c:1074
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
Definition: slru.c:375

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

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

Variable Documentation

◆ XactCtlData

SlruCtlData XactCtlData
static

Definition at line 108 of file clog.c.