PostgreSQL Source Code  git master
subtrans.c File Reference
#include "postgres.h"
#include "access/slru.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "utils/guc_hooks.h"
#include "utils/snapmgr.h"
Include dependency graph for subtrans.c:

Go to the source code of this file.

Macros

#define SUBTRANS_XACTS_PER_PAGE   (BLCKSZ / sizeof(TransactionId))
 
#define TransactionIdToEntry(xid)   ((xid) % (TransactionId) SUBTRANS_XACTS_PER_PAGE)
 
#define SubTransCtl   (&SubTransCtlData)
 

Functions

static int64 TransactionIdToPage (TransactionId xid)
 
static int ZeroSUBTRANSPage (int64 pageno)
 
static bool SubTransPagePrecedes (int64 page1, int64 page2)
 
void SubTransSetParent (TransactionId xid, TransactionId parent)
 
TransactionId SubTransGetParent (TransactionId xid)
 
TransactionId SubTransGetTopmostTransaction (TransactionId xid)
 
static int SUBTRANSShmemBuffers (void)
 
Size SUBTRANSShmemSize (void)
 
void SUBTRANSShmemInit (void)
 
bool check_subtrans_buffers (int *newval, void **extra, GucSource source)
 
void BootStrapSUBTRANS (void)
 
void StartupSUBTRANS (TransactionId oldestActiveXID)
 
void CheckPointSUBTRANS (void)
 
void ExtendSUBTRANS (TransactionId newestXact)
 
void TruncateSUBTRANS (TransactionId oldestXact)
 

Variables

static SlruCtlData SubTransCtlData
 

Macro Definition Documentation

◆ SUBTRANS_XACTS_PER_PAGE

#define SUBTRANS_XACTS_PER_PAGE   (BLCKSZ / sizeof(TransactionId))

Definition at line 54 of file subtrans.c.

◆ SubTransCtl

#define SubTransCtl   (&SubTransCtlData)

Definition at line 74 of file subtrans.c.

◆ TransactionIdToEntry

#define TransactionIdToEntry (   xid)    ((xid) % (TransactionId) SUBTRANS_XACTS_PER_PAGE)

Definition at line 66 of file subtrans.c.

Function Documentation

◆ BootStrapSUBTRANS()

void BootStrapSUBTRANS ( void  )

Definition at line 270 of file subtrans.c.

271 {
272  int slotno;
274 
276 
277  /* Create and zero the first page of the subtrans log */
278  slotno = ZeroSUBTRANSPage(0);
279 
280  /* Make sure it's written out */
282  Assert(!SubTransCtl->shared->page_dirty[slotno]);
283 
284  LWLockRelease(lock);
285 }
#define Assert(condition)
Definition: c.h:861
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
static int ZeroSUBTRANSPage(int64 pageno)
Definition: subtrans.c:296
#define SubTransCtl
Definition: subtrans.c:74

References Assert, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SimpleLruGetBankLock(), SimpleLruWritePage(), SubTransCtl, and ZeroSUBTRANSPage().

Referenced by BootStrapXLOG().

◆ check_subtrans_buffers()

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

Definition at line 254 of file subtrans.c.

255 {
256  return check_slru_buffers("subtransaction_buffers", newval);
257 }
#define newval
bool check_slru_buffers(const char *name, int *newval)
Definition: slru.c:355

References check_slru_buffers(), and newval.

◆ CheckPointSUBTRANS()

void CheckPointSUBTRANS ( void  )

Definition at line 355 of file subtrans.c.

356 {
357  /*
358  * Write dirty SUBTRANS pages to disk
359  *
360  * This is not actually necessary from a correctness point of view. We do
361  * it merely to improve the odds that writing of dirty pages is done by
362  * the checkpoint process and not by backends.
363  */
364  TRACE_POSTGRESQL_SUBTRANS_CHECKPOINT_START(true);
366  TRACE_POSTGRESQL_SUBTRANS_CHECKPOINT_DONE(true);
367 }
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1322

References SimpleLruWriteAll(), and SubTransCtl.

Referenced by CheckPointGuts().

◆ ExtendSUBTRANS()

void ExtendSUBTRANS ( TransactionId  newestXact)

Definition at line 379 of file subtrans.c.

380 {
381  int64 pageno;
382  LWLock *lock;
383 
384  /*
385  * No work except at first XID of a page. But beware: just after
386  * wraparound, the first XID of page zero is FirstNormalTransactionId.
387  */
388  if (TransactionIdToEntry(newestXact) != 0 &&
390  return;
391 
392  pageno = TransactionIdToPage(newestXact);
393 
394  lock = SimpleLruGetBankLock(SubTransCtl, pageno);
396 
397  /* Zero the page */
398  ZeroSUBTRANSPage(pageno);
399 
400  LWLockRelease(lock);
401 }
#define TransactionIdToEntry(xid)
Definition: subtrans.c:66
static int64 TransactionIdToPage(TransactionId xid)
Definition: subtrans.c:61
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define FirstNormalTransactionId
Definition: transam.h:34

References FirstNormalTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SimpleLruGetBankLock(), SubTransCtl, TransactionIdEquals, TransactionIdToEntry, TransactionIdToPage(), and ZeroSUBTRANSPage().

Referenced by GetNewTransactionId(), ProcArrayApplyRecoveryInfo(), and RecordKnownAssignedTransactionIds().

◆ StartupSUBTRANS()

void StartupSUBTRANS ( TransactionId  oldestActiveXID)

Definition at line 309 of file subtrans.c.

310 {
311  FullTransactionId nextXid;
312  int64 startPage;
313  int64 endPage;
314  LWLock *prevlock = NULL;
315  LWLock *lock;
316 
317  /*
318  * Since we don't expect pg_subtrans to be valid across crashes, we
319  * initialize the currently-active page(s) to zeroes during startup.
320  * Whenever we advance into a new page, ExtendSUBTRANS will likewise zero
321  * the new page without regard to whatever was previously on disk.
322  */
323  startPage = TransactionIdToPage(oldestActiveXID);
324  nextXid = TransamVariables->nextXid;
325  endPage = TransactionIdToPage(XidFromFullTransactionId(nextXid));
326 
327  for (;;)
328  {
329  lock = SimpleLruGetBankLock(SubTransCtl, startPage);
330  if (prevlock != lock)
331  {
332  if (prevlock)
333  LWLockRelease(prevlock);
335  prevlock = lock;
336  }
337 
338  (void) ZeroSUBTRANSPage(startPage);
339  if (startPage == endPage)
340  break;
341 
342  startPage++;
343  /* must account for wraparound */
344  if (startPage > TransactionIdToPage(MaxTransactionId))
345  startPage = 0;
346  }
347 
348  LWLockRelease(lock);
349 }
FullTransactionId nextXid
Definition: transam.h:220
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define MaxTransactionId
Definition: transam.h:35
TransamVariablesData * TransamVariables
Definition: varsup.c:34

References LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), MaxTransactionId, TransamVariablesData::nextXid, SimpleLruGetBankLock(), SubTransCtl, TransactionIdToPage(), TransamVariables, XidFromFullTransactionId, and ZeroSUBTRANSPage().

Referenced by StartupXLOG().

◆ SubTransGetParent()

TransactionId SubTransGetParent ( TransactionId  xid)

Definition at line 122 of file subtrans.c.

123 {
124  int64 pageno = TransactionIdToPage(xid);
125  int entryno = TransactionIdToEntry(xid);
126  int slotno;
127  TransactionId *ptr;
128  TransactionId parent;
129 
130  /* Can't ask about stuff that might not be around anymore */
132 
133  /* Bootstrap and frozen XIDs have no parent */
134  if (!TransactionIdIsNormal(xid))
135  return InvalidTransactionId;
136 
137  /* lock is acquired by SimpleLruReadPage_ReadOnly */
138 
139  slotno = SimpleLruReadPage_ReadOnly(SubTransCtl, pageno, xid);
140  ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno];
141  ptr += entryno;
142 
143  parent = *ptr;
144 
146 
147  return parent;
148 }
uint32 TransactionId
Definition: c.h:655
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int64 pageno, TransactionId xid)
Definition: slru.c:605
TransactionId TransactionXmin
Definition: snapmgr.c:98
bool TransactionIdFollowsOrEquals(TransactionId id1, TransactionId id2)
Definition: transam.c:329
#define InvalidTransactionId
Definition: transam.h:31
#define TransactionIdIsNormal(xid)
Definition: transam.h:42

References Assert, InvalidTransactionId, LWLockRelease(), SimpleLruGetBankLock(), SimpleLruReadPage_ReadOnly(), SubTransCtl, TransactionIdFollowsOrEquals(), TransactionIdIsNormal, TransactionIdToEntry, TransactionIdToPage(), and TransactionXmin.

Referenced by SubTransGetTopmostTransaction(), TransactionIdDidAbort(), and TransactionIdDidCommit().

◆ SubTransGetTopmostTransaction()

TransactionId SubTransGetTopmostTransaction ( TransactionId  xid)

Definition at line 163 of file subtrans.c.

164 {
165  TransactionId parentXid = xid,
166  previousXid = xid;
167 
168  /* Can't ask about stuff that might not be around anymore */
170 
171  while (TransactionIdIsValid(parentXid))
172  {
173  previousXid = parentXid;
174  if (TransactionIdPrecedes(parentXid, TransactionXmin))
175  break;
176  parentXid = SubTransGetParent(parentXid);
177 
178  /*
179  * By convention the parent xid gets allocated first, so should always
180  * precede the child xid. Anything else points to a corrupted data
181  * structure that could lead to an infinite loop, so exit.
182  */
183  if (!TransactionIdPrecedes(parentXid, previousXid))
184  elog(ERROR, "pg_subtrans contains invalid entry: xid %u points to parent xid %u",
185  previousXid, parentXid);
186  }
187 
188  Assert(TransactionIdIsValid(previousXid));
189 
190  return previousXid;
191 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
TransactionId SubTransGetParent(TransactionId xid)
Definition: subtrans.c:122
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References Assert, elog, ERROR, SubTransGetParent(), TransactionIdFollowsOrEquals(), TransactionIdIsValid, TransactionIdPrecedes(), and TransactionXmin.

Referenced by ConditionalXactLockTableWait(), HeapCheckForSerializableConflictOut(), TransactionIdIsInProgress(), XactLockTableWait(), and XidInMVCCSnapshot().

◆ SubTransPagePrecedes()

static bool SubTransPagePrecedes ( int64  page1,
int64  page2 
)
static

Definition at line 435 of file subtrans.c.

436 {
437  TransactionId xid1;
438  TransactionId xid2;
439 
440  xid1 = ((TransactionId) page1) * SUBTRANS_XACTS_PER_PAGE;
441  xid1 += FirstNormalTransactionId + 1;
442  xid2 = ((TransactionId) page2) * SUBTRANS_XACTS_PER_PAGE;
443  xid2 += FirstNormalTransactionId + 1;
444 
445  return (TransactionIdPrecedes(xid1, xid2) &&
447 }
#define SUBTRANS_XACTS_PER_PAGE
Definition: subtrans.c:54

References FirstNormalTransactionId, SUBTRANS_XACTS_PER_PAGE, and TransactionIdPrecedes().

Referenced by SUBTRANSShmemInit().

◆ SubTransSetParent()

void SubTransSetParent ( TransactionId  xid,
TransactionId  parent 
)

Definition at line 85 of file subtrans.c.

86 {
87  int64 pageno = TransactionIdToPage(xid);
88  int entryno = TransactionIdToEntry(xid);
89  int slotno;
90  LWLock *lock;
91  TransactionId *ptr;
92 
94  Assert(TransactionIdFollows(xid, parent));
95 
96  lock = SimpleLruGetBankLock(SubTransCtl, pageno);
98 
99  slotno = SimpleLruReadPage(SubTransCtl, pageno, true, xid);
100  ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno];
101  ptr += entryno;
102 
103  /*
104  * It's possible we'll try to set the parent xid multiple times but we
105  * shouldn't ever be changing the xid from one valid xid to another valid
106  * xid, which would corrupt the data structure.
107  */
108  if (*ptr != parent)
109  {
110  Assert(*ptr == InvalidTransactionId);
111  *ptr = parent;
112  SubTransCtl->shared->page_dirty[slotno] = true;
113  }
114 
115  LWLockRelease(lock);
116 }
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
int SimpleLruReadPage(SlruCtl ctl, int64 pageno, bool write_ok, TransactionId xid)
Definition: slru.c:502
bool TransactionIdFollows(TransactionId id1, TransactionId id2)
Definition: transam.c:314

References Assert, if(), InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SimpleLruGetBankLock(), SimpleLruReadPage(), SubTransCtl, TransactionIdFollows(), TransactionIdIsValid, TransactionIdToEntry, and TransactionIdToPage().

Referenced by AssignTransactionId(), ProcArrayApplyXidAssignment(), and ProcessTwoPhaseBuffer().

◆ SUBTRANSShmemBuffers()

static int SUBTRANSShmemBuffers ( void  )
static

Definition at line 201 of file subtrans.c.

202 {
203  /* auto-tune based on shared buffers */
204  if (subtransaction_buffers == 0)
205  return SimpleLruAutotuneBuffers(512, 1024);
206 
208 }
#define Min(x, y)
Definition: c.h:1007
#define Max(x, y)
Definition: c.h:1001
int subtransaction_buffers
Definition: globals.c:165
int SimpleLruAutotuneBuffers(int divisor, int max)
Definition: slru.c:232
#define SLRU_MAX_ALLOWED_BUFFERS
Definition: slru.h:24

References Max, Min, SimpleLruAutotuneBuffers(), SLRU_MAX_ALLOWED_BUFFERS, and subtransaction_buffers.

Referenced by SUBTRANSShmemInit(), and SUBTRANSShmemSize().

◆ SUBTRANSShmemInit()

void SUBTRANSShmemInit ( void  )

Definition at line 220 of file subtrans.c.

221 {
222  /* If auto-tuning is requested, now is the time to do it */
223  if (subtransaction_buffers == 0)
224  {
225  char buf[32];
226 
227  snprintf(buf, sizeof(buf), "%d", SUBTRANSShmemBuffers());
228  SetConfigOption("subtransaction_buffers", buf, PGC_POSTMASTER,
230 
231  /*
232  * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT.
233  * However, if the DBA explicitly set subtransaction_buffers = 0 in
234  * the config file, then PGC_S_DYNAMIC_DEFAULT will fail to override
235  * that and we must force the matter with PGC_S_OVERRIDE.
236  */
237  if (subtransaction_buffers == 0) /* failed to apply it? */
238  SetConfigOption("subtransaction_buffers", buf, PGC_POSTMASTER,
240  }
242 
243  SubTransCtl->PagePrecedes = SubTransPagePrecedes;
244  SimpleLruInit(SubTransCtl, "subtransaction", SUBTRANSShmemBuffers(), 0,
245  "pg_subtrans", LWTRANCHE_SUBTRANS_BUFFER,
248 }
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition: guc.c:4290
@ PGC_S_DYNAMIC_DEFAULT
Definition: guc.h:110
@ PGC_S_OVERRIDE
Definition: guc.h:119
@ PGC_POSTMASTER
Definition: guc.h:70
@ LWTRANCHE_SUBTRANS_BUFFER
Definition: lwlock.h:181
@ LWTRANCHE_SUBTRANS_SLRU
Definition: lwlock.h:215
static char * buf
Definition: pg_test_fsync.c:73
#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
static int SUBTRANSShmemBuffers(void)
Definition: subtrans.c:201
static bool SubTransPagePrecedes(int64 page1, int64 page2)
Definition: subtrans.c:435
@ SYNC_HANDLER_NONE
Definition: sync.h:42

References Assert, buf, LWTRANCHE_SUBTRANS_BUFFER, LWTRANCHE_SUBTRANS_SLRU, PGC_POSTMASTER, PGC_S_DYNAMIC_DEFAULT, PGC_S_OVERRIDE, SetConfigOption(), SimpleLruInit(), SlruPagePrecedesUnitTests, snprintf, SUBTRANS_XACTS_PER_PAGE, subtransaction_buffers, SubTransCtl, SubTransPagePrecedes(), SUBTRANSShmemBuffers(), and SYNC_HANDLER_NONE.

Referenced by CreateOrAttachShmemStructs().

◆ SUBTRANSShmemSize()

Size SUBTRANSShmemSize ( void  )

Definition at line 214 of file subtrans.c.

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

References SimpleLruShmemSize(), and SUBTRANSShmemBuffers().

Referenced by CalculateShmemSize().

◆ TransactionIdToPage()

static int64 TransactionIdToPage ( TransactionId  xid)
inlinestatic

Definition at line 61 of file subtrans.c.

62 {
63  return xid / (int64) SUBTRANS_XACTS_PER_PAGE;
64 }

References SUBTRANS_XACTS_PER_PAGE.

Referenced by ExtendSUBTRANS(), StartupSUBTRANS(), SubTransGetParent(), SubTransSetParent(), and TruncateSUBTRANS().

◆ TruncateSUBTRANS()

void TruncateSUBTRANS ( TransactionId  oldestXact)

Definition at line 411 of file subtrans.c.

412 {
413  int64 cutoffPage;
414 
415  /*
416  * The cutoff point is the start of the segment containing oldestXact. We
417  * pass the *page* containing oldestXact to SimpleLruTruncate. We step
418  * back one transaction to avoid passing a cutoff page that hasn't been
419  * created yet in the rare case that oldestXact would be the first item on
420  * a page and oldestXact == next XID. In that case, if we didn't subtract
421  * one, we'd trigger SimpleLruTruncate's wraparound detection.
422  */
423  TransactionIdRetreat(oldestXact);
424  cutoffPage = TransactionIdToPage(oldestXact);
425 
426  SimpleLruTruncate(SubTransCtl, cutoffPage);
427 }
void SimpleLruTruncate(SlruCtl ctl, int64 cutoffPage)
Definition: slru.c:1408
#define TransactionIdRetreat(dest)
Definition: transam.h:141

References SimpleLruTruncate(), SubTransCtl, TransactionIdRetreat, and TransactionIdToPage().

Referenced by CreateCheckPoint(), and CreateRestartPoint().

◆ ZeroSUBTRANSPage()

static int ZeroSUBTRANSPage ( int64  pageno)
static

Definition at line 296 of file subtrans.c.

297 {
298  return SimpleLruZeroPage(SubTransCtl, pageno);
299 }
int SimpleLruZeroPage(SlruCtl ctl, int64 pageno)
Definition: slru.c:375

References SimpleLruZeroPage(), and SubTransCtl.

Referenced by BootStrapSUBTRANS(), ExtendSUBTRANS(), and StartupSUBTRANS().

Variable Documentation

◆ SubTransCtlData

SlruCtlData SubTransCtlData
static

Definition at line 72 of file subtrans.c.