PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 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 ClogCtl   (&ClogCtlData)
 

Functions

static int ZeroCLOGPage (int pageno, bool writeXlog)
 
static bool CLOGPagePrecedes (int page1, int page2)
 
static void WriteZeroPageXlogRec (int pageno)
 
static void WriteTruncateXlogRec (int pageno, TransactionId oldestXact, Oid oldestXidDb)
 
static void TransactionIdSetPageStatus (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
 
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)
 
void TransactionIdSetTreeStatus (TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn)
 
XidStatus TransactionIdGetStatus (TransactionId xid, XLogRecPtr *lsn)
 
Size CLOGShmemBuffers (void)
 
Size CLOGShmemSize (void)
 
void CLOGShmemInit (void)
 
void BootStrapCLOG (void)
 
void StartupCLOG (void)
 
void TrimCLOG (void)
 
void ShutdownCLOG (void)
 
void CheckPointCLOG (void)
 
void ExtendCLOG (TransactionId newestXact)
 
void TruncateCLOG (TransactionId oldestXact, Oid oldestxid_datoid)
 
void clog_redo (XLogReaderState *record)
 

Variables

static SlruCtlData ClogCtlData
 

Macro Definition Documentation

#define CLOG_BITS_PER_XACT   2

Definition at line 57 of file clog.c.

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

#define CLOG_LSNS_PER_PAGE   (CLOG_XACTS_PER_PAGE / CLOG_XACTS_PER_LSN_GROUP)

Definition at line 69 of file clog.c.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

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

Definition at line 60 of file clog.c.

Referenced by TransactionIdGetStatus(), and TransactionIdSetStatusBit().

#define CLOG_XACTS_PER_BYTE   4

Definition at line 58 of file clog.c.

#define CLOG_XACTS_PER_LSN_GROUP   32 /* keep this a power of 2 */

Definition at line 68 of file clog.c.

#define CLOG_XACTS_PER_PAGE   (BLCKSZ * CLOG_XACTS_PER_BYTE)

Definition at line 59 of file clog.c.

Referenced by CLOGPagePrecedes().

#define GetLSNIndex (   slotno,
  xid 
)
Value:
((slotno) * CLOG_LSNS_PER_PAGE + \
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:59
uint32 TransactionId
Definition: c.h:397
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:69
#define CLOG_XACTS_PER_LSN_GROUP
Definition: clog.c:68

Definition at line 71 of file clog.c.

Referenced by TransactionIdGetStatus(), and TransactionIdSetStatusBit().

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

Definition at line 65 of file clog.c.

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

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

Definition at line 64 of file clog.c.

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

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

Definition at line 63 of file clog.c.

Referenced by ExtendCLOG(), and TrimCLOG().

Function Documentation

void BootStrapCLOG ( void  )

Definition at line 464 of file clog.c.

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

Referenced by BootStrapXLOG().

465 {
466  int slotno;
467 
468  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
469 
470  /* Create and zero the first page of the commit log */
471  slotno = ZeroCLOGPage(0, false);
472 
473  /* Make sure it's written out */
474  SimpleLruWritePage(ClogCtl, slotno);
475  Assert(!ClogCtl->shared->page_dirty[slotno]);
476 
477  LWLockRelease(CLogControlLock);
478 }
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ClogCtl
Definition: clog.c:80
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:574
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:490
void CheckPointCLOG ( void  )

Definition at line 594 of file clog.c.

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

Referenced by CheckPointGuts().

595 {
596  /* Flush dirty CLOG pages to disk */
597  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
598  SimpleLruFlush(ClogCtl, true);
599 
600  /*
601  * fsync pg_xact to ensure that any files flushed previously are durably
602  * on disk.
603  */
604  fsync_fname("pg_xact", true);
605 
606  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
607 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:567
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1100
#define ClogCtl
Definition: clog.c:80
void clog_redo ( XLogReaderState record)

Definition at line 759 of file clog.c.

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

760 {
761  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
762 
763  /* Backup blocks are not used in clog records */
764  Assert(!XLogRecHasAnyBlockRefs(record));
765 
766  if (info == CLOG_ZEROPAGE)
767  {
768  int pageno;
769  int slotno;
770 
771  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
772 
773  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
774 
775  slotno = ZeroCLOGPage(pageno, false);
776  SimpleLruWritePage(ClogCtl, slotno);
777  Assert(!ClogCtl->shared->page_dirty[slotno]);
778 
779  LWLockRelease(CLogControlLock);
780  }
781  else if (info == CLOG_TRUNCATE)
782  {
783  xl_clog_truncate xlrec;
784 
785  memcpy(&xlrec, XLogRecGetData(record), sizeof(xl_clog_truncate));
786 
787  /*
788  * During XLOG replay, latest_page_number isn't set up yet; insert a
789  * suitable value to bypass the sanity test in SimpleLruTruncate.
790  */
791  ClogCtl->shared->latest_page_number = xlrec.pageno;
792 
794 
796  }
797  else
798  elog(PANIC, "clog_redo: unknown op code %u", info);
799 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1165
unsigned char uint8
Definition: c.h:266
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ClogCtl
Definition: clog.c:80
#define CLOG_ZEROPAGE
Definition: clog.h:54
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:271
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:574
int pageno
Definition: clog.h:33
#define CLOG_TRUNCATE
Definition: clog.h:55
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:216
TransactionId oldestXact
Definition: clog.h:34
#define Assert(condition)
Definition: c.h:675
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:490
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:222
#define elog
Definition: elog.h:219
static bool CLOGPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 708 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

709 {
710  TransactionId xid1;
711  TransactionId xid2;
712 
713  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
714  xid1 += FirstNormalTransactionId;
715  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
716  xid2 += FirstNormalTransactionId;
717 
718  return TransactionIdPrecedes(xid1, xid2);
719 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:59
uint32 TransactionId
Definition: c.h:397
#define FirstNormalTransactionId
Definition: transam.h:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
Size CLOGShmemBuffers ( void  )

Definition at line 435 of file clog.c.

References Max, Min, and NBuffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

436 {
437  return Min(128, Max(4, NBuffers / 512));
438 }
#define Min(x, y)
Definition: c.h:806
#define Max(x, y)
Definition: c.h:800
int NBuffers
Definition: globals.c:122
void CLOGShmemInit ( void  )

Definition at line 450 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

451 {
452  ClogCtl->PagePrecedes = CLOGPagePrecedes;
454  CLogControlLock, "pg_xact", LWTRANCHE_CLOG_BUFFERS);
455 }
#define ClogCtl
Definition: clog.c:80
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:69
static bool CLOGPagePrecedes(int page1, int page2)
Definition: clog.c:708
Size CLOGShmemBuffers(void)
Definition: clog.c:435
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
Definition: slru.c:165
Size CLOGShmemSize ( void  )

Definition at line 444 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

445 {
447 }
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:145
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:69
Size CLOGShmemBuffers(void)
Definition: clog.c:435
void ExtendCLOG ( TransactionId  newestXact)

Definition at line 619 of file clog.c.

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

Referenced by GetNewTransactionId().

620 {
621  int pageno;
622 
623  /*
624  * No work except at first XID of a page. But beware: just after
625  * wraparound, the first XID of page zero is FirstNormalTransactionId.
626  */
627  if (TransactionIdToPgIndex(newestXact) != 0 &&
629  return;
630 
631  pageno = TransactionIdToPage(newestXact);
632 
633  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
634 
635  /* Zero the page and make an XLOG entry about it */
636  ZeroCLOGPage(pageno, true);
637 
638  LWLockRelease(CLogControlLock);
639 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define TransactionIdToPgIndex(xid)
Definition: clog.c:63
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define FirstNormalTransactionId
Definition: transam.h:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:490
static void set_status_by_pages ( int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn 
)
static

Definition at line 223 of file clog.c.

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

Referenced by TransactionIdSetTreeStatus().

225 {
226  int pageno = TransactionIdToPage(subxids[0]);
227  int offset = 0;
228  int i = 0;
229 
230  while (i < nsubxids)
231  {
232  int num_on_page = 0;
233 
234  while (TransactionIdToPage(subxids[i]) == pageno && i < nsubxids)
235  {
236  num_on_page++;
237  i++;
238  }
239 
241  num_on_page, subxids + offset,
242  status, lsn, pageno);
243  offset = i;
244  pageno = TransactionIdToPage(subxids[offset]);
245  }
246 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
#define InvalidTransactionId
Definition: transam.h:31
int i
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:255
void ShutdownCLOG ( void  )

Definition at line 575 of file clog.c.

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

Referenced by ShutdownXLOG().

576 {
577  /* Flush dirty CLOG pages to disk */
578  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(false);
579  SimpleLruFlush(ClogCtl, false);
580 
581  /*
582  * fsync pg_xact to ensure that any files flushed previously are durably
583  * on disk.
584  */
585  fsync_fname("pg_xact", true);
586 
587  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(false);
588 }
void fsync_fname(const char *fname, bool isdir)
Definition: fd.c:567
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1100
#define ClogCtl
Definition: clog.c:80
void StartupCLOG ( void  )

Definition at line 507 of file clog.c.

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

Referenced by StartupXLOG().

508 {
510  int pageno = TransactionIdToPage(xid);
511 
512  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
513 
514  /*
515  * Initialize our idea of the latest page number.
516  */
517  ClogCtl->shared->latest_page_number = pageno;
518 
519  LWLockRelease(CLogControlLock);
520 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
uint32 TransactionId
Definition: c.h:397
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ClogCtl
Definition: clog.c:80
TransactionId nextXid
Definition: transam.h:117
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
XidStatus TransactionIdGetStatus ( TransactionId  xid,
XLogRecPtr lsn 
)

Definition at line 393 of file clog.c.

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

Referenced by TransactionIdGetCommitLSN(), and TransactionLogFetch().

394 {
395  int pageno = TransactionIdToPage(xid);
396  int byteno = TransactionIdToByte(xid);
397  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
398  int slotno;
399  int lsnindex;
400  char *byteptr;
402 
403  /* lock is acquired by SimpleLruReadPage_ReadOnly */
404 
405  slotno = SimpleLruReadPage_ReadOnly(ClogCtl, pageno, xid);
406  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
407 
408  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
409 
410  lsnindex = GetLSNIndex(slotno, xid);
411  *lsn = ClogCtl->shared->group_lsn[lsnindex];
412 
413  LWLockRelease(CLogControlLock);
414 
415  return status;
416 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:65
#define CLOG_XACT_BITMASK
Definition: clog.c:60
#define TransactionIdToPage(xid)
Definition: clog.c:62
#define GetLSNIndex(slotno, xid)
Definition: clog.c:71
int XidStatus
Definition: clog.h:24
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ClogCtl
Definition: clog.c:80
#define CLOG_BITS_PER_XACT
Definition: clog.c:57
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:463
#define TransactionIdToByte(xid)
Definition: clog.c:64
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
static void TransactionIdSetPageStatus ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn,
int  pageno 
)
static

Definition at line 255 of file clog.c.

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

Referenced by set_status_by_pages(), and TransactionIdSetTreeStatus().

258 {
259  int slotno;
260  int i;
261 
265 
266  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
267 
268  /*
269  * If we're doing an async commit (ie, lsn is valid), then we must wait
270  * for any active write on the page slot to complete. Otherwise our
271  * update could reach disk in that write, which will not do since we
272  * mustn't let it reach disk until we've done the appropriate WAL flush.
273  * But when lsn is invalid, it's OK to scribble on a page while it is
274  * write-busy, since we don't care if the update reaches disk sooner than
275  * we think.
276  */
277  slotno = SimpleLruReadPage(ClogCtl, pageno, XLogRecPtrIsInvalid(lsn), xid);
278 
279  /*
280  * Set the main transaction id, if any.
281  *
282  * If we update more than one xid on this page while it is being written
283  * out, we might find that some of the bits go to disk and others don't.
284  * If we are updating commits on the page with the top-level xid that
285  * could break atomicity, so we subcommit the subxids first before we mark
286  * the top-level commit.
287  */
288  if (TransactionIdIsValid(xid))
289  {
290  /* Subtransactions first, if needed ... */
292  {
293  for (i = 0; i < nsubxids; i++)
294  {
295  Assert(ClogCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
296  TransactionIdSetStatusBit(subxids[i],
298  lsn, slotno);
299  }
300  }
301 
302  /* ... then the main transaction */
303  TransactionIdSetStatusBit(xid, status, lsn, slotno);
304  }
305 
306  /* Set the subtransactions */
307  for (i = 0; i < nsubxids; i++)
308  {
309  Assert(ClogCtl->shared->page_number[slotno] == TransactionIdToPage(subxids[i]));
310  TransactionIdSetStatusBit(subxids[i], status, lsn, slotno);
311  }
312 
313  ClogCtl->shared->page_dirty[slotno] = true;
314 
315  LWLockRelease(CLogControlLock);
316 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:27
static void TransactionIdSetStatusBit(TransactionId xid, XidStatus status, XLogRecPtr lsn, int slotno)
Definition: clog.c:324
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ClogCtl
Definition: clog.c:80
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:371
#define TRANSACTION_STATUS_ABORTED
Definition: clog.h:28
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:29
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:675
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
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:224
static void TransactionIdSetStatusBit ( TransactionId  xid,
XidStatus  status,
XLogRecPtr  lsn,
int  slotno 
)
static

Definition at line 324 of file clog.c.

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

Referenced by TransactionIdSetPageStatus().

325 {
326  int byteno = TransactionIdToByte(xid);
327  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
328  char *byteptr;
329  char byteval;
330  char curval;
331 
332  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
333  curval = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
334 
335  /*
336  * When replaying transactions during recovery we still need to perform
337  * the two phases of subcommit and then commit. However, some transactions
338  * are already correctly marked, so we just treat those as a no-op which
339  * allows us to keep the following Assert as restrictive as possible.
340  */
343  return;
344 
345  /*
346  * Current state change should be from 0 or subcommitted to target state
347  * or we should already be there when replaying changes during recovery.
348  */
349  Assert(curval == 0 ||
352  curval == status);
353 
354  /* note this assumes exclusive access to the clog page */
355  byteval = *byteptr;
356  byteval &= ~(((1 << CLOG_BITS_PER_XACT) - 1) << bshift);
357  byteval |= (status << bshift);
358  *byteptr = byteval;
359 
360  /*
361  * Update the group LSN if the transaction completion LSN is higher.
362  *
363  * Note: lsn will be invalid when supplied during InRecovery processing,
364  * so we don't need to do anything special to avoid LSN updates during
365  * recovery. After recovery completes the next clog change will set the
366  * LSN correctly.
367  */
368  if (!XLogRecPtrIsInvalid(lsn))
369  {
370  int lsnindex = GetLSNIndex(slotno, xid);
371 
372  if (ClogCtl->shared->group_lsn[lsnindex] < lsn)
373  ClogCtl->shared->group_lsn[lsnindex] = lsn;
374  }
375 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:65
#define CLOG_XACT_BITMASK
Definition: clog.c:60
#define TRANSACTION_STATUS_COMMITTED
Definition: clog.h:27
#define GetLSNIndex(slotno, xid)
Definition: clog.c:71
bool InRecovery
Definition: xlog.c:192
#define ClogCtl
Definition: clog.c:80
#define TRANSACTION_STATUS_SUB_COMMITTED
Definition: clog.h:29
#define CLOG_BITS_PER_XACT
Definition: clog.c:57
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:675
#define TransactionIdToByte(xid)
Definition: clog.c:64
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:224
#define TRANSACTION_STATUS_IN_PROGRESS
Definition: clog.h:26
void TransactionIdSetTreeStatus ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn 
)

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

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

Definition at line 526 of file clog.c.

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

Referenced by StartupXLOG().

527 {
529  int pageno = TransactionIdToPage(xid);
530 
531  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
532 
533  /*
534  * Re-Initialize our idea of the latest page number.
535  */
536  ClogCtl->shared->latest_page_number = pageno;
537 
538  /*
539  * Zero out the remainder of the current clog page. Under normal
540  * circumstances it should be zeroes already, but it seems at least
541  * theoretically possible that XLOG replay will have settled on a nextXID
542  * value that is less than the last XID actually used and marked by the
543  * previous database lifecycle (since subtransaction commit writes clog
544  * but makes no WAL entry). Let's just be safe. (We need not worry about
545  * pages beyond the current one, since those will be zeroed when first
546  * used. For the same reason, there is no need to do anything when
547  * nextXid is exactly at a page boundary; and it's likely that the
548  * "current" page doesn't exist yet in that case.)
549  */
550  if (TransactionIdToPgIndex(xid) != 0)
551  {
552  int byteno = TransactionIdToByte(xid);
553  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
554  int slotno;
555  char *byteptr;
556 
557  slotno = SimpleLruReadPage(ClogCtl, pageno, false, xid);
558  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
559 
560  /* Zero so-far-unused positions in the current byte */
561  *byteptr &= (1 << bshift) - 1;
562  /* Zero the rest of the page */
563  MemSet(byteptr + 1, 0, BLCKSZ - byteno - 1);
564 
565  ClogCtl->shared->page_dirty[slotno] = true;
566  }
567 
568  LWLockRelease(CLogControlLock);
569 }
#define TransactionIdToBIndex(xid)
Definition: clog.c:65
#define TransactionIdToPage(xid)
Definition: clog.c:62
uint32 TransactionId
Definition: c.h:397
#define TransactionIdToPgIndex(xid)
Definition: clog.c:63
#define MemSet(start, val, len)
Definition: c.h:857
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1715
#define ClogCtl
Definition: clog.c:80
TransactionId nextXid
Definition: transam.h:117
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:371
VariableCache ShmemVariableCache
Definition: varsup.c:34
#define CLOG_BITS_PER_XACT
Definition: clog.c:57
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1111
#define TransactionIdToByte(xid)
Definition: clog.c:64
void TruncateCLOG ( TransactionId  oldestXact,
Oid  oldestxid_datoid 
)

Definition at line 658 of file clog.c.

References AdvanceOldestClogXid(), Assert, ClogCtl, VariableCacheData::oldestXid, ShmemVariableCache, SimpleLruTruncate(), SlruScanDirCbReportPresence(), SlruScanDirectory(), TransactionIdPrecedesOrEquals(), TransactionIdToPage, and WriteTruncateXlogRec().

Referenced by vac_truncate_clog().

659 {
660  int cutoffPage;
661 
662  /*
663  * The cutoff point is the start of the segment containing oldestXact. We
664  * pass the *page* containing oldestXact to SimpleLruTruncate.
665  */
666  cutoffPage = TransactionIdToPage(oldestXact);
667 
668  /* Check to see if there's any files that could be removed */
670  return; /* nothing to remove */
671 
672  /*
673  * Advance oldestClogXid before truncating clog, so concurrent xact status
674  * lookups can ensure they don't attempt to access truncated-away clog.
675  *
676  * It's only necessary to do this if we will actually truncate away clog
677  * pages.
678  */
679  AdvanceOldestClogXid(oldestXact);
680 
681  /* vac_truncate_clog already advanced oldestXid */
684 
685  /*
686  * Write XLOG record and flush XLOG to disk. We record the oldest xid
687  * we're keeping information about here so we can ensure that it's always
688  * ahead of clog truncation in case we crash, and so a standby finds out
689  * the new valid xid before the next checkpoint.
690  */
691  WriteTruncateXlogRec(cutoffPage, oldestXact, oldestxid_datoid);
692 
693  /* Now we can remove the old CLOG segment(s) */
694  SimpleLruTruncate(ClogCtl, cutoffPage);
695 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1165
TransactionId oldestXid
Definition: transam.h:119
#define ClogCtl
Definition: clog.c:80
void AdvanceOldestClogXid(TransactionId oldest_datfrozenxid)
Definition: varsup.c:271
bool TransactionIdPrecedesOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:319
VariableCache ShmemVariableCache
Definition: varsup.c:34
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1318
#define Assert(condition)
Definition: c.h:675
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1373
static void WriteTruncateXlogRec(int pageno, TransactionId oldestXact, Oid oldestXidDb)
Definition: clog.c:740
static void WriteTruncateXlogRec ( int  pageno,
TransactionId  oldestXact,
Oid  oldestXidDb 
)
static

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

741 {
742  XLogRecPtr recptr;
743  xl_clog_truncate xlrec;
744 
745  xlrec.pageno = pageno;
746  xlrec.oldestXact = oldestXact;
747  xlrec.oldestXactDb = oldestXactDb;
748 
749  XLogBeginInsert();
750  XLogRegisterData((char *) (&xlrec), sizeof(xl_clog_truncate));
751  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
752  XLogFlush(recptr);
753 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2758
int pageno
Definition: clog.h:33
#define CLOG_TRUNCATE
Definition: clog.h:55
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
TransactionId oldestXact
Definition: clog.h:34
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Oid oldestXactDb
Definition: clog.h:35
void XLogBeginInsert(void)
Definition: xloginsert.c:120
static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 726 of file clog.c.

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

Referenced by ZeroCLOGPage().

727 {
728  XLogBeginInsert();
729  XLogRegisterData((char *) (&pageno), sizeof(int));
730  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
731 }
#define CLOG_ZEROPAGE
Definition: clog.h:54
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void XLogBeginInsert(void)
Definition: xloginsert.c:120
static int ZeroCLOGPage ( int  pageno,
bool  writeXlog 
)
static

Definition at line 490 of file clog.c.

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

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

491 {
492  int slotno;
493 
494  slotno = SimpleLruZeroPage(ClogCtl, pageno);
495 
496  if (writeXlog)
497  WriteZeroPageXlogRec(pageno);
498 
499  return slotno;
500 }
static void WriteZeroPageXlogRec(int pageno)
Definition: clog.c:726
#define ClogCtl
Definition: clog.c:80
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
Definition: slru.c:259

Variable Documentation

SlruCtlData ClogCtlData
static

Definition at line 78 of file clog.c.