PostgreSQL Source Code  git master
commit_ts.c File Reference
#include "postgres.h"
#include "access/commit_ts.h"
#include "access/htup_details.h"
#include "access/slru.h"
#include "access/transam.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "storage/shmem.h"
#include "utils/builtins.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
Include dependency graph for commit_ts.c:

Go to the source code of this file.

Data Structures

struct  CommitTimestampEntry
 
struct  CommitTimestampShared
 

Macros

#define SizeOfCommitTimestampEntry
 
#define COMMIT_TS_XACTS_PER_PAGE    (BLCKSZ / SizeOfCommitTimestampEntry)
 
#define TransactionIdToCTsPage(xid)    ((xid) / (TransactionId) COMMIT_TS_XACTS_PER_PAGE)
 
#define TransactionIdToCTsEntry(xid)    ((xid) % (TransactionId) COMMIT_TS_XACTS_PER_PAGE)
 
#define CommitTsCtl   (&CommitTsCtlData)
 

Typedefs

typedef struct CommitTimestampEntry CommitTimestampEntry
 
typedef struct CommitTimestampShared CommitTimestampShared
 

Functions

static void SetXidCommitTsInPage (TransactionId xid, int nsubxids, TransactionId *subxids, TimestampTz ts, RepOriginId nodeid, int pageno)
 
static void TransactionIdSetCommitTs (TransactionId xid, TimestampTz ts, RepOriginId nodeid, int slotno)
 
static void error_commit_ts_disabled (void)
 
static int ZeroCommitTsPage (int pageno, bool writeXlog)
 
static bool CommitTsPagePrecedes (int page1, int page2)
 
static void ActivateCommitTs (void)
 
static void DeactivateCommitTs (void)
 
static void WriteZeroPageXlogRec (int pageno)
 
static void WriteTruncateXlogRec (int pageno, TransactionId oldestXid)
 
void TransactionTreeSetCommitTsData (TransactionId xid, int nsubxids, TransactionId *subxids, TimestampTz timestamp, RepOriginId nodeid)
 
bool TransactionIdGetCommitTsData (TransactionId xid, TimestampTz *ts, RepOriginId *nodeid)
 
TransactionId GetLatestCommitTsData (TimestampTz *ts, RepOriginId *nodeid)
 
Datum pg_xact_commit_timestamp (PG_FUNCTION_ARGS)
 
Datum pg_last_committed_xact (PG_FUNCTION_ARGS)
 
Datum pg_xact_commit_timestamp_origin (PG_FUNCTION_ARGS)
 
Size CommitTsShmemBuffers (void)
 
Size CommitTsShmemSize (void)
 
void CommitTsShmemInit (void)
 
void BootStrapCommitTs (void)
 
void StartupCommitTs (void)
 
void CompleteCommitTsInitialization (void)
 
void CommitTsParameterChange (bool newvalue, bool oldvalue)
 
void CheckPointCommitTs (void)
 
void ExtendCommitTs (TransactionId newestXact)
 
void TruncateCommitTs (TransactionId oldestXact)
 
void SetCommitTsLimit (TransactionId oldestXact, TransactionId newestXact)
 
void AdvanceOldestCommitTsXid (TransactionId oldestXact)
 
void commit_ts_redo (XLogReaderState *record)
 
int committssyncfiletag (const FileTag *ftag, char *path)
 

Variables

static SlruCtlData CommitTsCtlData
 
static CommitTimestampSharedcommitTsShared
 
bool track_commit_timestamp
 

Macro Definition Documentation

◆ COMMIT_TS_XACTS_PER_PAGE

#define COMMIT_TS_XACTS_PER_PAGE    (BLCKSZ / SizeOfCommitTimestampEntry)

Definition at line 68 of file commit_ts.c.

◆ CommitTsCtl

#define CommitTsCtl   (&CommitTsCtlData)

Definition at line 81 of file commit_ts.c.

◆ SizeOfCommitTimestampEntry

#define SizeOfCommitTimestampEntry
Value:
sizeof(RepOriginId))
#define offsetof(type, field)
Definition: c.h:727
uint16 RepOriginId
Definition: xlogdefs.h:65

Definition at line 65 of file commit_ts.c.

◆ TransactionIdToCTsEntry

#define TransactionIdToCTsEntry (   xid)     ((xid) % (TransactionId) COMMIT_TS_XACTS_PER_PAGE)

Definition at line 73 of file commit_ts.c.

◆ TransactionIdToCTsPage

#define TransactionIdToCTsPage (   xid)     ((xid) / (TransactionId) COMMIT_TS_XACTS_PER_PAGE)

Definition at line 71 of file commit_ts.c.

Typedef Documentation

◆ CommitTimestampEntry

◆ CommitTimestampShared

Function Documentation

◆ ActivateCommitTs()

static void ActivateCommitTs ( void  )
static

Definition at line 683 of file commit_ts.c.

684 {
685  TransactionId xid;
686  int pageno;
687 
688  /* If we've done this already, there's nothing to do */
689  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
691  {
692  LWLockRelease(CommitTsLock);
693  return;
694  }
695  LWLockRelease(CommitTsLock);
696 
698  pageno = TransactionIdToCTsPage(xid);
699 
700  /*
701  * Re-Initialize our idea of the latest page number.
702  */
703  LWLockAcquire(CommitTsSLRULock, LW_EXCLUSIVE);
704  CommitTsCtl->shared->latest_page_number = pageno;
705  LWLockRelease(CommitTsSLRULock);
706 
707  /*
708  * If CommitTs is enabled, but it wasn't in the previous server run, we
709  * need to set the oldest and newest values to the next Xid; that way, we
710  * will not try to read data that might not have been set.
711  *
712  * XXX does this have a problem if a server is started with commitTs
713  * enabled, then started with commitTs disabled, then restarted with it
714  * enabled again? It doesn't look like it does, because there should be a
715  * checkpoint that sets the value to InvalidTransactionId at end of
716  * recovery; and so any chance of injecting new transactions without
717  * CommitTs values would occur after the oldestCommitTsXid has been set to
718  * Invalid temporarily.
719  */
720  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
722  {
725  }
726  LWLockRelease(CommitTsLock);
727 
728  /* Create the current segment file, if necessary */
730  {
731  int slotno;
732 
733  LWLockAcquire(CommitTsSLRULock, LW_EXCLUSIVE);
734  slotno = ZeroCommitTsPage(pageno, false);
736  Assert(!CommitTsCtl->shared->page_dirty[slotno]);
737  LWLockRelease(CommitTsSLRULock);
738  }
739 
740  /* Change the activation status in shared memory. */
741  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
743  LWLockRelease(CommitTsLock);
744 }
uint32 TransactionId
Definition: c.h:587
static CommitTimestampShared * commitTsShared
Definition: commit_ts.c:101
static int ZeroCommitTsPage(int pageno, bool writeXlog)
Definition: commit_ts.c:593
#define CommitTsCtl
Definition: commit_ts.c:81
#define TransactionIdToCTsPage(xid)
Definition: commit_ts.c:71
Assert(fmt[strlen(fmt) - 1] !='\n')
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1196
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1800
@ LW_EXCLUSIVE
Definition: lwlock.h:104
void SimpleLruWritePage(SlruCtl ctl, int slotno)
Definition: slru.c:614
bool SimpleLruDoesPhysicalPageExist(SlruCtl ctl, int pageno)
Definition: slru.c:626
FullTransactionId nextXid
Definition: transam.h:220
TransactionId newestCommitTsXid
Definition: transam.h:233
TransactionId oldestCommitTsXid
Definition: transam.h:232
static TransactionId ReadNextTransactionId(void)
Definition: transam.h:316
#define InvalidTransactionId
Definition: transam.h:31
#define XidFromFullTransactionId(x)
Definition: transam.h:48
VariableCache ShmemVariableCache
Definition: varsup.c:34

References Assert(), CommitTimestampShared::commitTsActive, CommitTsCtl, commitTsShared, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::newestCommitTsXid, VariableCacheData::nextXid, VariableCacheData::oldestCommitTsXid, ReadNextTransactionId(), ShmemVariableCache, SimpleLruDoesPhysicalPageExist(), SimpleLruWritePage(), TransactionIdToCTsPage, XidFromFullTransactionId, and ZeroCommitTsPage().

Referenced by CommitTsParameterChange(), CompleteCommitTsInitialization(), and StartupCommitTs().

◆ AdvanceOldestCommitTsXid()

void AdvanceOldestCommitTsXid ( TransactionId  oldestXact)

Definition at line 908 of file commit_ts.c.

909 {
910  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
914  LWLockRelease(CommitTsLock);
915 }
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300

References InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::oldestCommitTsXid, ShmemVariableCache, and TransactionIdPrecedes().

Referenced by commit_ts_redo(), and vac_truncate_clog().

◆ BootStrapCommitTs()

void BootStrapCommitTs ( void  )

Definition at line 574 of file commit_ts.c.

575 {
576  /*
577  * Nothing to do here at present, unlike most other SLRU modules; segments
578  * are created when the server is started with this module enabled. See
579  * ActivateCommitTs.
580  */
581 }

Referenced by BootStrapXLOG().

◆ CheckPointCommitTs()

void CheckPointCommitTs ( void  )

Definition at line 795 of file commit_ts.c.

796 {
797  /*
798  * Write dirty CommitTs pages to disk. This may result in sync requests
799  * queued for later handling by ProcessSyncRequests(), as part of the
800  * checkpoint.
801  */
803 }
void SimpleLruWriteAll(SlruCtl ctl, bool allow_redirtied)
Definition: slru.c:1156

References CommitTsCtl, and SimpleLruWriteAll().

Referenced by CheckPointGuts().

◆ commit_ts_redo()

void commit_ts_redo ( XLogReaderState record)

Definition at line 988 of file commit_ts.c.

989 {
990  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
991 
992  /* Backup blocks are not used in commit_ts records */
993  Assert(!XLogRecHasAnyBlockRefs(record));
994 
995  if (info == COMMIT_TS_ZEROPAGE)
996  {
997  int pageno;
998  int slotno;
999 
1000  memcpy(&pageno, XLogRecGetData(record), sizeof(int));
1001 
1002  LWLockAcquire(CommitTsSLRULock, LW_EXCLUSIVE);
1003 
1004  slotno = ZeroCommitTsPage(pageno, false);
1006  Assert(!CommitTsCtl->shared->page_dirty[slotno]);
1007 
1008  LWLockRelease(CommitTsSLRULock);
1009  }
1010  else if (info == COMMIT_TS_TRUNCATE)
1011  {
1013 
1015 
1016  /*
1017  * During XLOG replay, latest_page_number isn't set up yet; insert a
1018  * suitable value to bypass the sanity test in SimpleLruTruncate.
1019  */
1020  CommitTsCtl->shared->latest_page_number = trunc->pageno;
1021 
1023  }
1024  else
1025  elog(PANIC, "commit_ts_redo: unknown op code %u", info);
1026 }
unsigned char uint8
Definition: c.h:439
void AdvanceOldestCommitTsXid(TransactionId oldestXact)
Definition: commit_ts.c:908
#define COMMIT_TS_ZEROPAGE
Definition: commit_ts.h:47
#define COMMIT_TS_TRUNCATE
Definition: commit_ts.h:48
#define PANIC
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:218
void SimpleLruTruncate(SlruCtl ctl, int cutoffPage)
Definition: slru.c:1226
TransactionId oldestXid
Definition: commit_ts.h:64
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:408
#define XLogRecGetData(decoder)
Definition: xlogreader.h:413
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:415
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References AdvanceOldestCommitTsXid(), Assert(), COMMIT_TS_TRUNCATE, COMMIT_TS_ZEROPAGE, CommitTsCtl, elog, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), xl_commit_ts_truncate::oldestXid, xl_commit_ts_truncate::pageno, PANIC, SimpleLruTruncate(), SimpleLruWritePage(), XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, XLR_INFO_MASK, and ZeroCommitTsPage().

◆ CommitTsPagePrecedes()

static bool CommitTsPagePrecedes ( int  page1,
int  page2 
)
static

Definition at line 942 of file commit_ts.c.

943 {
944  TransactionId xid1;
945  TransactionId xid2;
946 
947  xid1 = ((TransactionId) page1) * COMMIT_TS_XACTS_PER_PAGE;
948  xid1 += FirstNormalTransactionId + 1;
949  xid2 = ((TransactionId) page2) * COMMIT_TS_XACTS_PER_PAGE;
950  xid2 += FirstNormalTransactionId + 1;
951 
952  return (TransactionIdPrecedes(xid1, xid2) &&
954 }
#define COMMIT_TS_XACTS_PER_PAGE
Definition: commit_ts.c:68
#define FirstNormalTransactionId
Definition: transam.h:34

References COMMIT_TS_XACTS_PER_PAGE, FirstNormalTransactionId, and TransactionIdPrecedes().

Referenced by CommitTsShmemInit().

◆ CommitTsParameterChange()

void CommitTsParameterChange ( bool  newvalue,
bool  oldvalue 
)

Definition at line 642 of file commit_ts.c.

643 {
644  /*
645  * If the commit_ts module is disabled in this server and we get word from
646  * the primary server that it is enabled there, activate it so that we can
647  * replay future WAL records involving it; also mark it as active on
648  * pg_control. If the old value was already set, we already did this, so
649  * don't do anything.
650  *
651  * If the module is disabled in the primary, disable it here too, unless
652  * the module is enabled locally.
653  *
654  * Note this only runs in the recovery process, so an unlocked read is
655  * fine.
656  */
657  if (newvalue)
658  {
661  }
662  else if (commitTsShared->commitTsActive)
664 }
static void DeactivateCommitTs(void)
Definition: commit_ts.c:757
static void ActivateCommitTs(void)
Definition: commit_ts.c:683

References ActivateCommitTs(), CommitTimestampShared::commitTsActive, commitTsShared, and DeactivateCommitTs().

Referenced by xlog_redo().

◆ CommitTsShmemBuffers()

Size CommitTsShmemBuffers ( void  )

Definition at line 519 of file commit_ts.c.

520 {
521  return Min(256, Max(4, NBuffers / 256));
522 }
#define Min(x, y)
Definition: c.h:986
#define Max(x, y)
Definition: c.h:980
int NBuffers
Definition: globals.c:136

References Max, Min, and NBuffers.

Referenced by CommitTsShmemInit(), and CommitTsShmemSize().

◆ CommitTsShmemInit()

void CommitTsShmemInit ( void  )

Definition at line 539 of file commit_ts.c.

540 {
541  bool found;
542 
543  CommitTsCtl->PagePrecedes = CommitTsPagePrecedes;
545  CommitTsSLRULock, "pg_commit_ts",
549 
550  commitTsShared = ShmemInitStruct("CommitTs shared",
551  sizeof(CommitTimestampShared),
552  &found);
553 
554  if (!IsUnderPostmaster)
555  {
556  Assert(!found);
557 
562  }
563  else
564  Assert(found);
565 }
Size CommitTsShmemBuffers(void)
Definition: commit_ts.c:519
static bool CommitTsPagePrecedes(int page1, int page2)
Definition: commit_ts.c:942
#define TIMESTAMP_NOBEGIN(j)
Definition: timestamp.h:151
bool IsUnderPostmaster
Definition: globals.c:113
@ LWTRANCHE_COMMITTS_BUFFER
Definition: lwlock.h:170
#define InvalidRepOriginId
Definition: origin.h:33
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:396
void SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns, LWLock *ctllock, const char *subdir, int tranche_id, SyncRequestHandler sync_handler)
Definition: slru.c:187
#define SlruPagePrecedesUnitTests(ctl, per_page)
Definition: slru.h:156
TimestampTz time
Definition: commit_ts.c:61
RepOriginId nodeid
Definition: commit_ts.c:62
CommitTimestampEntry dataLastCommit
Definition: commit_ts.c:97
TransactionId xidLastCommit
Definition: commit_ts.c:96
@ SYNC_HANDLER_COMMIT_TS
Definition: sync.h:39

References Assert(), COMMIT_TS_XACTS_PER_PAGE, CommitTimestampShared::commitTsActive, CommitTsCtl, CommitTsPagePrecedes(), commitTsShared, CommitTsShmemBuffers(), CommitTimestampShared::dataLastCommit, InvalidRepOriginId, InvalidTransactionId, IsUnderPostmaster, LWTRANCHE_COMMITTS_BUFFER, CommitTimestampEntry::nodeid, ShmemInitStruct(), SimpleLruInit(), SlruPagePrecedesUnitTests, SYNC_HANDLER_COMMIT_TS, CommitTimestampEntry::time, TIMESTAMP_NOBEGIN, and CommitTimestampShared::xidLastCommit.

Referenced by CreateSharedMemoryAndSemaphores().

◆ CommitTsShmemSize()

Size CommitTsShmemSize ( void  )

Definition at line 528 of file commit_ts.c.

529 {
531  sizeof(CommitTimestampShared);
532 }
struct CommitTimestampShared CommitTimestampShared
Size SimpleLruShmemSize(int nslots, int nlsns)
Definition: slru.c:156

References CommitTsShmemBuffers(), and SimpleLruShmemSize().

Referenced by CalculateShmemSize().

◆ committssyncfiletag()

int committssyncfiletag ( const FileTag ftag,
char *  path 
)

Definition at line 1032 of file commit_ts.c.

1033 {
1034  return SlruSyncFileTag(CommitTsCtl, ftag, path);
1035 }
int SlruSyncFileTag(SlruCtl ctl, const FileTag *ftag, char *path)
Definition: slru.c:1593

References CommitTsCtl, and SlruSyncFileTag().

◆ CompleteCommitTsInitialization()

void CompleteCommitTsInitialization ( void  )

Definition at line 620 of file commit_ts.c.

621 {
622  /*
623  * If the feature is not enabled, turn it off for good. This also removes
624  * any leftover data.
625  *
626  * Conversely, we activate the module if the feature is enabled. This is
627  * necessary for primary and standby as the activation depends on the
628  * control file contents at the beginning of recovery or when a
629  * XLOG_PARAMETER_CHANGE is replayed.
630  */
633  else
635 }
bool track_commit_timestamp
Definition: commit_ts.c:105

References ActivateCommitTs(), DeactivateCommitTs(), and track_commit_timestamp.

Referenced by StartupXLOG().

◆ DeactivateCommitTs()

static void DeactivateCommitTs ( void  )
static

Definition at line 757 of file commit_ts.c.

758 {
759  /*
760  * Cleanup the status in the shared memory.
761  *
762  * We reset everything in the commitTsShared record to prevent user from
763  * getting confusing data about last committed transaction on the standby
764  * when the module was activated repeatedly on the primary.
765  */
766  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
767 
772 
775 
776  LWLockRelease(CommitTsLock);
777 
778  /*
779  * Remove *all* files. This is necessary so that there are no leftover
780  * files; in the case where this feature is later enabled after running
781  * with it disabled for some time there may be a gap in the file sequence.
782  * (We can probably tolerate out-of-sequence files, as they are going to
783  * be overwritten anyway when we wrap around, but it seems better to be
784  * tidy.)
785  */
786  LWLockAcquire(CommitTsSLRULock, LW_EXCLUSIVE);
788  LWLockRelease(CommitTsSLRULock);
789 }
bool SlruScanDirCbDeleteAll(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1530
bool SlruScanDirectory(SlruCtl ctl, SlruScanCallback callback, void *data)
Definition: slru.c:1553

References CommitTimestampShared::commitTsActive, CommitTsCtl, commitTsShared, CommitTimestampShared::dataLastCommit, InvalidRepOriginId, InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::newestCommitTsXid, CommitTimestampEntry::nodeid, VariableCacheData::oldestCommitTsXid, ShmemVariableCache, SlruScanDirCbDeleteAll(), SlruScanDirectory(), CommitTimestampEntry::time, TIMESTAMP_NOBEGIN, and CommitTimestampShared::xidLastCommit.

Referenced by CommitTsParameterChange(), and CompleteCommitTsInitialization().

◆ error_commit_ts_disabled()

static void error_commit_ts_disabled ( void  )
static

Definition at line 376 of file commit_ts.c.

377 {
378  ereport(ERROR,
379  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
380  errmsg("could not get commit timestamp data"),
382  errhint("Make sure the configuration parameter \"%s\" is set on the primary server.",
383  "track_commit_timestamp") :
384  errhint("Make sure the configuration parameter \"%s\" is set.",
385  "track_commit_timestamp")));
386 }
int errhint(const char *fmt,...)
Definition: elog.c:1151
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define ereport(elevel,...)
Definition: elog.h:143
bool RecoveryInProgress(void)
Definition: xlog.c:5753

References ereport, errcode(), errhint(), errmsg(), ERROR, and RecoveryInProgress().

Referenced by GetLatestCommitTsData(), and TransactionIdGetCommitTsData().

◆ ExtendCommitTs()

void ExtendCommitTs ( TransactionId  newestXact)

Definition at line 817 of file commit_ts.c.

818 {
819  int pageno;
820 
821  /*
822  * Nothing to do if module not enabled. Note we do an unlocked read of
823  * the flag here, which is okay because this routine is only called from
824  * GetNewTransactionId, which is never called in a standby.
825  */
826  Assert(!InRecovery);
828  return;
829 
830  /*
831  * No work except at first XID of a page. But beware: just after
832  * wraparound, the first XID of page zero is FirstNormalTransactionId.
833  */
834  if (TransactionIdToCTsEntry(newestXact) != 0 &&
836  return;
837 
838  pageno = TransactionIdToCTsPage(newestXact);
839 
840  LWLockAcquire(CommitTsSLRULock, LW_EXCLUSIVE);
841 
842  /* Zero the page and make an XLOG entry about it */
843  ZeroCommitTsPage(pageno, !InRecovery);
844 
845  LWLockRelease(CommitTsSLRULock);
846 }
#define TransactionIdToCTsEntry(xid)
Definition: commit_ts.c:73
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
bool InRecovery
Definition: xlogutils.c:53

References Assert(), CommitTimestampShared::commitTsActive, commitTsShared, FirstNormalTransactionId, InRecovery, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), TransactionIdEquals, TransactionIdToCTsEntry, TransactionIdToCTsPage, and ZeroCommitTsPage().

Referenced by GetNewTransactionId().

◆ GetLatestCommitTsData()

TransactionId GetLatestCommitTsData ( TimestampTz ts,
RepOriginId nodeid 
)

Definition at line 355 of file commit_ts.c.

356 {
357  TransactionId xid;
358 
359  LWLockAcquire(CommitTsLock, LW_SHARED);
360 
361  /* Error if module not enabled */
364 
366  if (ts)
368  if (nodeid)
370  LWLockRelease(CommitTsLock);
371 
372  return xid;
373 }
static void error_commit_ts_disabled(void)
Definition: commit_ts.c:376
@ LW_SHARED
Definition: lwlock.h:105

References CommitTimestampShared::commitTsActive, commitTsShared, CommitTimestampShared::dataLastCommit, error_commit_ts_disabled(), LW_SHARED, LWLockAcquire(), LWLockRelease(), CommitTimestampEntry::nodeid, CommitTimestampEntry::time, and CommitTimestampShared::xidLastCommit.

Referenced by pg_last_committed_xact().

◆ pg_last_committed_xact()

Datum pg_last_committed_xact ( PG_FUNCTION_ARGS  )

Definition at line 415 of file commit_ts.c.

416 {
417  TransactionId xid;
418  RepOriginId nodeid;
419  TimestampTz ts;
420  Datum values[3];
421  bool nulls[3];
422  TupleDesc tupdesc;
423  HeapTuple htup;
424 
425  /* and construct a tuple with our data */
426  xid = GetLatestCommitTsData(&ts, &nodeid);
427 
428  /*
429  * Construct a tuple descriptor for the result row. This must match this
430  * function's pg_proc entry!
431  */
432  tupdesc = CreateTemplateTupleDesc(3);
433  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid",
434  XIDOID, -1, 0);
435  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "timestamp",
436  TIMESTAMPTZOID, -1, 0);
437  TupleDescInitEntry(tupdesc, (AttrNumber) 3, "roident",
438  OIDOID, -1, 0);
439  tupdesc = BlessTupleDesc(tupdesc);
440 
441  if (!TransactionIdIsNormal(xid))
442  {
443  memset(nulls, true, sizeof(nulls));
444  }
445  else
446  {
447  values[0] = TransactionIdGetDatum(xid);
448  nulls[0] = false;
449 
450  values[1] = TimestampTzGetDatum(ts);
451  nulls[1] = false;
452 
453  values[2] = ObjectIdGetDatum((Oid) nodeid);
454  nulls[2] = false;
455  }
456 
457  htup = heap_form_tuple(tupdesc, values, nulls);
458 
460 }
int16 AttrNumber
Definition: attnum.h:21
static Datum values[MAXATTR]
Definition: bootstrap.c:156
TransactionId GetLatestCommitTsData(TimestampTz *ts, RepOriginId *nodeid)
Definition: commit_ts.c:355
int64 TimestampTz
Definition: timestamp.h:39
TupleDesc BlessTupleDesc(TupleDesc tupdesc)
Definition: execTuples.c:2071
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:220
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define TransactionIdGetDatum(X)
Definition: postgres.h:565
uintptr_t Datum
Definition: postgres.h:411
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
unsigned int Oid
Definition: postgres_ext.h:31
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
TupleDesc CreateTemplateTupleDesc(int natts)
Definition: tupdesc.c:45
void TupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim)
Definition: tupdesc.c:583
#define TimestampTzGetDatum(X)
Definition: timestamp.h:32

References BlessTupleDesc(), CreateTemplateTupleDesc(), GetLatestCommitTsData(), heap_form_tuple(), HeapTupleGetDatum, ObjectIdGetDatum, PG_RETURN_DATUM, TimestampTzGetDatum, TransactionIdGetDatum, TransactionIdIsNormal, TupleDescInitEntry(), and values.

◆ pg_xact_commit_timestamp()

Datum pg_xact_commit_timestamp ( PG_FUNCTION_ARGS  )

Definition at line 392 of file commit_ts.c.

393 {
395  TimestampTz ts;
396  bool found;
397 
398  found = TransactionIdGetCommitTsData(xid, &ts, NULL);
399 
400  if (!found)
401  PG_RETURN_NULL();
402 
404 }
bool TransactionIdGetCommitTsData(TransactionId xid, TimestampTz *ts, RepOriginId *nodeid)
Definition: commit_ts.c:269
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_GETARG_TRANSACTIONID(n)
Definition: fmgr.h:279
#define PG_RETURN_TIMESTAMPTZ(x)
Definition: timestamp.h:40

References PG_GETARG_TRANSACTIONID, PG_RETURN_NULL, PG_RETURN_TIMESTAMPTZ, and TransactionIdGetCommitTsData().

◆ pg_xact_commit_timestamp_origin()

Datum pg_xact_commit_timestamp_origin ( PG_FUNCTION_ARGS  )

Definition at line 469 of file commit_ts.c.

470 {
472  RepOriginId nodeid;
473  TimestampTz ts;
474  Datum values[2];
475  bool nulls[2];
476  TupleDesc tupdesc;
477  HeapTuple htup;
478  bool found;
479 
480  found = TransactionIdGetCommitTsData(xid, &ts, &nodeid);
481 
482  /*
483  * Construct a tuple descriptor for the result row. This must match this
484  * function's pg_proc entry!
485  */
486  tupdesc = CreateTemplateTupleDesc(2);
487  TupleDescInitEntry(tupdesc, (AttrNumber) 1, "timestamp",
488  TIMESTAMPTZOID, -1, 0);
489  TupleDescInitEntry(tupdesc, (AttrNumber) 2, "roident",
490  OIDOID, -1, 0);
491  tupdesc = BlessTupleDesc(tupdesc);
492 
493  if (!found)
494  {
495  memset(nulls, true, sizeof(nulls));
496  }
497  else
498  {
499  values[0] = TimestampTzGetDatum(ts);
500  nulls[0] = false;
501 
502  values[1] = ObjectIdGetDatum((Oid) nodeid);
503  nulls[1] = false;
504  }
505 
506  htup = heap_form_tuple(tupdesc, values, nulls);
507 
509 }

References BlessTupleDesc(), CreateTemplateTupleDesc(), heap_form_tuple(), HeapTupleGetDatum, ObjectIdGetDatum, PG_GETARG_TRANSACTIONID, PG_RETURN_DATUM, TimestampTzGetDatum, TransactionIdGetCommitTsData(), TupleDescInitEntry(), and values.

◆ SetCommitTsLimit()

void SetCommitTsLimit ( TransactionId  oldestXact,
TransactionId  newestXact 
)

Definition at line 881 of file commit_ts.c.

882 {
883  /*
884  * Be careful not to overwrite values that are either further into the
885  * "future" or signal a disabled committs.
886  */
887  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
889  {
894  }
895  else
896  {
900  }
901  LWLockRelease(CommitTsLock);
902 }

References Assert(), InvalidTransactionId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::newestCommitTsXid, VariableCacheData::oldestCommitTsXid, ShmemVariableCache, and TransactionIdPrecedes().

Referenced by BootStrapXLOG(), and StartupXLOG().

◆ SetXidCommitTsInPage()

static void SetXidCommitTsInPage ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TimestampTz  ts,
RepOriginId  nodeid,
int  pageno 
)
static

Definition at line 218 of file commit_ts.c.

221 {
222  int slotno;
223  int i;
224 
225  LWLockAcquire(CommitTsSLRULock, LW_EXCLUSIVE);
226 
227  slotno = SimpleLruReadPage(CommitTsCtl, pageno, true, xid);
228 
229  TransactionIdSetCommitTs(xid, ts, nodeid, slotno);
230  for (i = 0; i < nsubxids; i++)
231  TransactionIdSetCommitTs(subxids[i], ts, nodeid, slotno);
232 
233  CommitTsCtl->shared->page_dirty[slotno] = true;
234 
235  LWLockRelease(CommitTsSLRULock);
236 }
static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts, RepOriginId nodeid, int slotno)
Definition: commit_ts.c:244
int i
Definition: isn.c:73
int SimpleLruReadPage(SlruCtl ctl, int pageno, bool write_ok, TransactionId xid)
Definition: slru.c:395

References CommitTsCtl, i, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), SimpleLruReadPage(), and TransactionIdSetCommitTs().

Referenced by TransactionTreeSetCommitTsData().

◆ StartupCommitTs()

void StartupCommitTs ( void  )

Definition at line 610 of file commit_ts.c.

611 {
613 }

References ActivateCommitTs().

Referenced by StartupXLOG().

◆ TransactionIdGetCommitTsData()

bool TransactionIdGetCommitTsData ( TransactionId  xid,
TimestampTz ts,
RepOriginId nodeid 
)

Definition at line 269 of file commit_ts.c.

271 {
272  int pageno = TransactionIdToCTsPage(xid);
273  int entryno = TransactionIdToCTsEntry(xid);
274  int slotno;
275  CommitTimestampEntry entry;
276  TransactionId oldestCommitTsXid;
277  TransactionId newestCommitTsXid;
278 
279  if (!TransactionIdIsValid(xid))
280  ereport(ERROR,
281  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
282  errmsg("cannot retrieve commit timestamp for transaction %u", xid)));
283  else if (!TransactionIdIsNormal(xid))
284  {
285  /* frozen and bootstrap xids are always committed far in the past */
286  *ts = 0;
287  if (nodeid)
288  *nodeid = 0;
289  return false;
290  }
291 
292  LWLockAcquire(CommitTsLock, LW_SHARED);
293 
294  /* Error if module not enabled */
297 
298  /*
299  * If we're asked for the cached value, return that. Otherwise, fall
300  * through to read from SLRU.
301  */
302  if (commitTsShared->xidLastCommit == xid)
303  {
305  if (nodeid)
307 
308  LWLockRelease(CommitTsLock);
309  return *ts != 0;
310  }
311 
312  oldestCommitTsXid = ShmemVariableCache->oldestCommitTsXid;
313  newestCommitTsXid = ShmemVariableCache->newestCommitTsXid;
314  /* neither is invalid, or both are */
315  Assert(TransactionIdIsValid(oldestCommitTsXid) == TransactionIdIsValid(newestCommitTsXid));
316  LWLockRelease(CommitTsLock);
317 
318  /*
319  * Return empty if the requested value is outside our valid range.
320  */
321  if (!TransactionIdIsValid(oldestCommitTsXid) ||
322  TransactionIdPrecedes(xid, oldestCommitTsXid) ||
323  TransactionIdPrecedes(newestCommitTsXid, xid))
324  {
325  *ts = 0;
326  if (nodeid)
327  *nodeid = InvalidRepOriginId;
328  return false;
329  }
330 
331  /* lock is acquired by SimpleLruReadPage_ReadOnly */
332  slotno = SimpleLruReadPage_ReadOnly(CommitTsCtl, pageno, xid);
333  memcpy(&entry,
334  CommitTsCtl->shared->page_buffer[slotno] +
335  SizeOfCommitTimestampEntry * entryno,
337 
338  *ts = entry.time;
339  if (nodeid)
340  *nodeid = entry.nodeid;
341 
342  LWLockRelease(CommitTsSLRULock);
343  return *ts != 0;
344 }
#define SizeOfCommitTimestampEntry
Definition: commit_ts.c:65
int SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid)
Definition: slru.c:495
#define TransactionIdIsValid(xid)
Definition: transam.h:41

References Assert(), CommitTimestampShared::commitTsActive, CommitTsCtl, commitTsShared, CommitTimestampShared::dataLastCommit, ereport, errcode(), errmsg(), ERROR, error_commit_ts_disabled(), InvalidRepOriginId, LW_SHARED, LWLockAcquire(), LWLockRelease(), VariableCacheData::newestCommitTsXid, CommitTimestampEntry::nodeid, VariableCacheData::oldestCommitTsXid, ShmemVariableCache, SimpleLruReadPage_ReadOnly(), SizeOfCommitTimestampEntry, CommitTimestampEntry::time, TransactionIdIsNormal, TransactionIdIsValid, TransactionIdPrecedes(), TransactionIdToCTsEntry, TransactionIdToCTsPage, and CommitTimestampShared::xidLastCommit.

Referenced by pg_xact_commit_timestamp(), and pg_xact_commit_timestamp_origin().

◆ TransactionIdSetCommitTs()

static void TransactionIdSetCommitTs ( TransactionId  xid,
TimestampTz  ts,
RepOriginId  nodeid,
int  slotno 
)
static

Definition at line 244 of file commit_ts.c.

246 {
247  int entryno = TransactionIdToCTsEntry(xid);
248  CommitTimestampEntry entry;
249 
251 
252  entry.time = ts;
253  entry.nodeid = nodeid;
254 
255  memcpy(CommitTsCtl->shared->page_buffer[slotno] +
256  SizeOfCommitTimestampEntry * entryno,
258 }

References Assert(), CommitTsCtl, CommitTimestampEntry::nodeid, SizeOfCommitTimestampEntry, CommitTimestampEntry::time, TransactionIdIsNormal, and TransactionIdToCTsEntry.

Referenced by SetXidCommitTsInPage().

◆ TransactionTreeSetCommitTsData()

void TransactionTreeSetCommitTsData ( TransactionId  xid,
int  nsubxids,
TransactionId subxids,
TimestampTz  timestamp,
RepOriginId  nodeid 
)

Definition at line 137 of file commit_ts.c.

140 {
141  int i;
142  TransactionId headxid;
143  TransactionId newestXact;
144 
145  /*
146  * No-op if the module is not active.
147  *
148  * An unlocked read here is fine, because in a standby (the only place
149  * where the flag can change in flight) this routine is only called by the
150  * recovery process, which is also the only process which can change the
151  * flag.
152  */
154  return;
155 
156  /*
157  * Figure out the latest Xid in this batch: either the last subxid if
158  * there's any, otherwise the parent xid.
159  */
160  if (nsubxids > 0)
161  newestXact = subxids[nsubxids - 1];
162  else
163  newestXact = xid;
164 
165  /*
166  * We split the xids to set the timestamp to in groups belonging to the
167  * same SLRU page; the first element in each such set is its head. The
168  * first group has the main XID as the head; subsequent sets use the first
169  * subxid not on the previous page as head. This way, we only have to
170  * lock/modify each SLRU page once.
171  */
172  headxid = xid;
173  i = 0;
174  for (;;)
175  {
176  int pageno = TransactionIdToCTsPage(headxid);
177  int j;
178 
179  for (j = i; j < nsubxids; j++)
180  {
181  if (TransactionIdToCTsPage(subxids[j]) != pageno)
182  break;
183  }
184  /* subxids[i..j] are on the same page as the head */
185 
186  SetXidCommitTsInPage(headxid, j - i, subxids + i, timestamp, nodeid,
187  pageno);
188 
189  /* if we wrote out all subxids, we're done. */
190  if (j >= nsubxids)
191  break;
192 
193  /*
194  * Set the new head and skip over it, as well as over the subxids we
195  * just wrote.
196  */
197  headxid = subxids[j];
198  i = j + 1;
199  }
200 
201  /* update the cached value in shared memory */
202  LWLockAcquire(CommitTsLock, LW_EXCLUSIVE);
206 
207  /* and move forwards our endpoint, if needed */
210  LWLockRelease(CommitTsLock);
211 }
static void SetXidCommitTsInPage(TransactionId xid, int nsubxids, TransactionId *subxids, TimestampTz ts, RepOriginId nodeid, int pageno)
Definition: commit_ts.c:218
int j
Definition: isn.c:74
int64 timestamp

References CommitTimestampShared::commitTsActive, commitTsShared, CommitTimestampShared::dataLastCommit, i, j, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::newestCommitTsXid, CommitTimestampEntry::nodeid, SetXidCommitTsInPage(), ShmemVariableCache, CommitTimestampEntry::time, TransactionIdPrecedes(), TransactionIdToCTsPage, and CommitTimestampShared::xidLastCommit.

Referenced by RecordTransactionCommit(), RecordTransactionCommitPrepared(), and xact_redo_commit().

◆ TruncateCommitTs()

void TruncateCommitTs ( TransactionId  oldestXact)

Definition at line 855 of file commit_ts.c.

856 {
857  int cutoffPage;
858 
859  /*
860  * The cutoff point is the start of the segment containing oldestXact. We
861  * pass the *page* containing oldestXact to SimpleLruTruncate.
862  */
863  cutoffPage = TransactionIdToCTsPage(oldestXact);
864 
865  /* Check to see if there's any files that could be removed */
867  &cutoffPage))
868  return; /* nothing to remove */
869 
870  /* Write XLOG record */
871  WriteTruncateXlogRec(cutoffPage, oldestXact);
872 
873  /* Now we can remove the old CommitTs segment(s) */
874  SimpleLruTruncate(CommitTsCtl, cutoffPage);
875 }
static void WriteTruncateXlogRec(int pageno, TransactionId oldestXid)
Definition: commit_ts.c:972
bool SlruScanDirCbReportPresence(SlruCtl ctl, char *filename, int segpage, void *data)
Definition: slru.c:1500

References CommitTsCtl, SimpleLruTruncate(), SlruScanDirCbReportPresence(), SlruScanDirectory(), TransactionIdToCTsPage, and WriteTruncateXlogRec().

Referenced by vac_truncate_clog().

◆ WriteTruncateXlogRec()

static void WriteTruncateXlogRec ( int  pageno,
TransactionId  oldestXid 
)
static

Definition at line 972 of file commit_ts.c.

973 {
974  xl_commit_ts_truncate xlrec;
975 
976  xlrec.pageno = pageno;
977  xlrec.oldestXid = oldestXid;
978 
979  XLogBeginInsert();
980  XLogRegisterData((char *) (&xlrec), SizeOfCommitTsTruncate);
981  (void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_TRUNCATE);
982 }
#define SizeOfCommitTsTruncate
Definition: commit_ts.h:67
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:443
void XLogBeginInsert(void)
Definition: xloginsert.c:150
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:351

References COMMIT_TS_TRUNCATE, xl_commit_ts_truncate::oldestXid, xl_commit_ts_truncate::pageno, SizeOfCommitTsTruncate, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by TruncateCommitTs().

◆ WriteZeroPageXlogRec()

static void WriteZeroPageXlogRec ( int  pageno)
static

Definition at line 961 of file commit_ts.c.

962 {
963  XLogBeginInsert();
964  XLogRegisterData((char *) (&pageno), sizeof(int));
965  (void) XLogInsert(RM_COMMIT_TS_ID, COMMIT_TS_ZEROPAGE);
966 }

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

Referenced by ZeroCommitTsPage().

◆ ZeroCommitTsPage()

static int ZeroCommitTsPage ( int  pageno,
bool  writeXlog 
)
static

Definition at line 593 of file commit_ts.c.

594 {
595  int slotno;
596 
597  slotno = SimpleLruZeroPage(CommitTsCtl, pageno);
598 
599  if (writeXlog)
600  WriteZeroPageXlogRec(pageno);
601 
602  return slotno;
603 }
static void WriteZeroPageXlogRec(int pageno)
Definition: commit_ts.c:961
int SimpleLruZeroPage(SlruCtl ctl, int pageno)
Definition: slru.c:280

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

Referenced by ActivateCommitTs(), commit_ts_redo(), and ExtendCommitTs().

Variable Documentation

◆ CommitTsCtlData

SlruCtlData CommitTsCtlData
static

Definition at line 79 of file commit_ts.c.

◆ commitTsShared

◆ track_commit_timestamp

bool track_commit_timestamp