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)
 
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)
 
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:394
#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 463 of file clog.c.

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

Referenced by BootStrapXLOG().

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

Definition at line 586 of file clog.c.

References ClogCtl, and SimpleLruFlush().

Referenced by CheckPointGuts().

587 {
588  /* Flush dirty CLOG pages to disk */
589  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(true);
590  SimpleLruFlush(ClogCtl, true);
591  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(true);
592 }
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1090
#define ClogCtl
Definition: clog.c:80
void clog_redo ( XLogReaderState record)

Definition at line 721 of file clog.c.

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

722 {
723  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
724 
725  /* Backup blocks are not used in clog records */
726  Assert(!XLogRecHasAnyBlockRefs(record));
727 
728  if (info == CLOG_ZEROPAGE)
729  {
730  int pageno;
731  int slotno;
732 
733  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
734 
735  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
736 
737  slotno = ZeroCLOGPage(pageno, false);
738  SimpleLruWritePage(ClogCtl, slotno);
739  Assert(!ClogCtl->shared->page_dirty[slotno]);
740 
741  LWLockRelease(CLogControlLock);
742  }
743  else if (info == CLOG_TRUNCATE)
744  {
745  int pageno;
746 
747  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
748 
749  /*
750  * During XLOG replay, latest_page_number isn't set up yet; insert a
751  * suitable value to bypass the sanity test in SimpleLruTruncate.
752  */
753  ClogCtl->shared->latest_page_number = pageno;
754 
755  SimpleLruTruncate(ClogCtl, pageno);
756  }
757  else
758  elog(PANIC, "clog_redo: unknown op code %u", info);
759 }
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1153
unsigned char uint8
Definition: c.h:263
#define PANIC
Definition: elog.h:53
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#define ClogCtl
Definition: clog.c:80
#define CLOG_ZEROPAGE
Definition: clog.h:48
#define XLogRecGetData(decoder)
Definition: xlogreader.h:202
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:573
#define CLOG_TRUNCATE
Definition: clog.h:49
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:198
#define Assert(condition)
Definition: c.h:671
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:489
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:204
#define elog
Definition: elog.h:219
static bool CLOGPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 675 of file clog.c.

References CLOG_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CLOGShmemInit().

676 {
677  TransactionId xid1;
678  TransactionId xid2;
679 
680  xid1 = ((TransactionId) page1) * CLOG_XACTS_PER_PAGE;
681  xid1 += FirstNormalTransactionId;
682  xid2 = ((TransactionId) page2) * CLOG_XACTS_PER_PAGE;
683  xid2 += FirstNormalTransactionId;
684 
685  return TransactionIdPrecedes(xid1, xid2);
686 }
#define CLOG_XACTS_PER_PAGE
Definition: clog.c:59
uint32 TransactionId
Definition: c.h:394
#define FirstNormalTransactionId
Definition: transam.h:34
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
Size CLOGShmemBuffers ( void  )

Definition at line 434 of file clog.c.

References Max, Min, and NBuffers.

Referenced by CLOGShmemInit(), and CLOGShmemSize().

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

Definition at line 449 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

450 {
451  ClogCtl->PagePrecedes = CLOGPagePrecedes;
453  CLogControlLock, "pg_clog", LWTRANCHE_CLOG_BUFFERS);
454 }
#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:675
Size CLOGShmemBuffers(void)
Definition: clog.c:434
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id)
Definition: slru.c:164
Size CLOGShmemSize ( void  )

Definition at line 443 of file clog.c.

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

Referenced by CreateSharedMemoryAndSemaphores().

444 {
446 }
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:144
#define CLOG_LSNS_PER_PAGE
Definition: clog.c:69
Size CLOGShmemBuffers(void)
Definition: clog.c:434
void ExtendCLOG ( TransactionId  newestXact)

Definition at line 604 of file clog.c.

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

Referenced by GetNewTransactionId().

605 {
606  int pageno;
607 
608  /*
609  * No work except at first XID of a page. But beware: just after
610  * wraparound, the first XID of page zero is FirstNormalTransactionId.
611  */
612  if (TransactionIdToPgIndex(newestXact) != 0 &&
614  return;
615 
616  pageno = TransactionIdToPage(newestXact);
617 
618  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
619 
620  /* Zero the page and make an XLOG entry about it */
621  ZeroCLOGPage(pageno, true);
622 
623  LWLockRelease(CLogControlLock);
624 }
#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:1714
#define FirstNormalTransactionId
Definition: transam.h:34
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1110
static int ZeroCLOGPage(int pageno, bool writeXlog)
Definition: clog.c:489
static void set_status_by_pages ( int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn 
)
static

Definition at line 222 of file clog.c.

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

Referenced by TransactionIdSetTreeStatus().

224 {
225  int pageno = TransactionIdToPage(subxids[0]);
226  int offset = 0;
227  int i = 0;
228 
229  while (i < nsubxids)
230  {
231  int num_on_page = 0;
232 
233  while (TransactionIdToPage(subxids[i]) == pageno && i < nsubxids)
234  {
235  num_on_page++;
236  i++;
237  }
238 
240  num_on_page, subxids + offset,
241  status, lsn, pageno);
242  offset = i;
243  pageno = TransactionIdToPage(subxids[offset]);
244  }
245 }
#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:222
static void TransactionIdSetPageStatus(TransactionId xid, int nsubxids, TransactionId *subxids, XidStatus status, XLogRecPtr lsn, int pageno)
Definition: clog.c:254
void ShutdownCLOG ( void  )

Definition at line 574 of file clog.c.

References ClogCtl, and SimpleLruFlush().

Referenced by ShutdownXLOG().

575 {
576  /* Flush dirty CLOG pages to disk */
577  TRACE_POSTGRESQL_CLOG_CHECKPOINT_START(false);
578  SimpleLruFlush(ClogCtl, false);
579  TRACE_POSTGRESQL_CLOG_CHECKPOINT_DONE(false);
580 }
void SimpleLruFlush(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1090
#define ClogCtl
Definition: clog.c:80
void StartupCLOG ( void  )

Definition at line 506 of file clog.c.

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

Referenced by StartupXLOG().

507 {
509  int pageno = TransactionIdToPage(xid);
510 
511  LWLockAcquire(CLogControlLock, LW_EXCLUSIVE);
512 
513  /*
514  * Initialize our idea of the latest page number.
515  */
516  ClogCtl->shared->latest_page_number = pageno;
517 
518  LWLockRelease(CLogControlLock);
519 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
uint32 TransactionId
Definition: c.h:394
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1714
#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:1110
XidStatus TransactionIdGetStatus ( TransactionId  xid,
XLogRecPtr lsn 
)

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

393 {
394  int pageno = TransactionIdToPage(xid);
395  int byteno = TransactionIdToByte(xid);
396  int bshift = TransactionIdToBIndex(xid) * CLOG_BITS_PER_XACT;
397  int slotno;
398  int lsnindex;
399  char *byteptr;
401 
402  /* lock is acquired by SimpleLruReadPage_ReadOnly */
403 
404  slotno = SimpleLruReadPage_ReadOnly(ClogCtl, pageno, xid);
405  byteptr = ClogCtl->shared->page_buffer[slotno] + byteno;
406 
407  status = (*byteptr >> bshift) & CLOG_XACT_BITMASK;
408 
409  lsnindex = GetLSNIndex(slotno, xid);
410  *lsn = ClogCtl->shared->group_lsn[lsnindex];
411 
412  LWLockRelease(CLogControlLock);
413 
414  return status;
415 }
#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:1714
#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:462
#define TransactionIdToByte(xid)
Definition: clog.c:64
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
static void TransactionIdSetPageStatus ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
XidStatus  status,
XLogRecPtr  lsn,
int  pageno 
)
static

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

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

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

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

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

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

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

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

Definition at line 643 of file clog.c.

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

Referenced by vac_truncate_clog().

644 {
645  int cutoffPage;
646 
647  /*
648  * The cutoff point is the start of the segment containing oldestXact. We
649  * pass the *page* containing oldestXact to SimpleLruTruncate.
650  */
651  cutoffPage = TransactionIdToPage(oldestXact);
652 
653  /* Check to see if there's any files that could be removed */
655  return; /* nothing to remove */
656 
657  /* Write XLOG record and flush XLOG to disk */
658  WriteTruncateXlogRec(cutoffPage);
659 
660  /* Now we can remove the old CLOG segment(s) */
661  SimpleLruTruncate(ClogCtl, cutoffPage);
662 }
#define TransactionIdToPage(xid)
Definition: clog.c:62
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1153
#define ClogCtl
Definition: clog.c:80
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1306
static void WriteTruncateXlogRec(int pageno)
Definition: clog.c:707
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1361
static void WriteTruncateXlogRec ( int  pageno)
static

Definition at line 707 of file clog.c.

References CLOG_TRUNCATE, XLogBeginInsert(), XLogFlush(), XLogInsert(), and XLogRegisterData().

Referenced by TruncateCLOG().

708 {
709  XLogRecPtr recptr;
710 
711  XLogBeginInsert();
712  XLogRegisterData((char *) (&pageno), sizeof(int));
713  recptr = XLogInsert(RM_CLOG_ID, CLOG_TRUNCATE);
714  XLogFlush(recptr);
715 }
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2745
#define CLOG_TRUNCATE
Definition: clog.h:49
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void XLogBeginInsert(void)
Definition: xloginsert.c:120
static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 693 of file clog.c.

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

Referenced by ZeroCLOGPage().

694 {
695  XLogBeginInsert();
696  XLogRegisterData((char *) (&pageno), sizeof(int));
697  (void) XLogInsert(RM_CLOG_ID, CLOG_ZEROPAGE);
698 }
#define CLOG_ZEROPAGE
Definition: clog.h:48
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 489 of file clog.c.

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

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

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

Variable Documentation

SlruCtlData ClogCtlData
static

Definition at line 78 of file clog.c.