PostgreSQL Source Code git master
Loading...
Searching...
No Matches
commit_ts.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * commit_ts.c
4 * PostgreSQL commit timestamp manager
5 *
6 * This module is a pg_xact-like system that stores the commit timestamp
7 * for each transaction.
8 *
9 * XLOG interactions: this module generates an XLOG record whenever a new
10 * CommitTs page is initialized to zeroes. Other writes of CommitTS come
11 * from recording of transaction commit in xact.c, which generates its own
12 * XLOG records for these events and will re-perform the status update on
13 * redo; so we need make no additional XLOG entry here.
14 *
15 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
16 * Portions Copyright (c) 1994, Regents of the University of California
17 *
18 * src/backend/access/transam/commit_ts.c
19 *
20 *-------------------------------------------------------------------------
21 */
22#include "postgres.h"
23
24#include "access/commit_ts.h"
25#include "access/htup_details.h"
26#include "access/slru.h"
27#include "access/transam.h"
28#include "access/xloginsert.h"
29#include "access/xlogutils.h"
30#include "funcapi.h"
31#include "miscadmin.h"
32#include "storage/shmem.h"
33#include "storage/subsystems.h"
34#include "utils/fmgrprotos.h"
35#include "utils/guc_hooks.h"
36#include "utils/timestamp.h"
37
38/*
39 * Defines for CommitTs page sizes. A page is the same BLCKSZ as is used
40 * everywhere else in Postgres.
41 *
42 * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
43 * CommitTs page numbering also wraps around at
44 * 0xFFFFFFFF/COMMIT_TS_XACTS_PER_PAGE, and CommitTs segment numbering at
45 * 0xFFFFFFFF/COMMIT_TS_XACTS_PER_PAGE/SLRU_PAGES_PER_SEGMENT. We need take no
46 * explicit notice of that fact in this module, except when comparing segment
47 * and page numbers in TruncateCommitTs (see CommitTsPagePrecedes).
48 */
49
50/*
51 * We need 8+2 bytes per xact. Note that enlarging this struct might mean
52 * the largest possible file name is more than 5 chars long; see
53 * SlruScanDirectory.
54 */
60
61#define SizeOfCommitTimestampEntry (offsetof(CommitTimestampEntry, nodeid) + \
62 sizeof(ReplOriginId))
63
64#define COMMIT_TS_XACTS_PER_PAGE \
65 (BLCKSZ / SizeOfCommitTimestampEntry)
66
67
68/*
69 * Although we return an int64 the actual value can't currently exceed
70 * 0xFFFFFFFF/COMMIT_TS_XACTS_PER_PAGE.
71 */
72static inline int64
77
78#define TransactionIdToCTsEntry(xid) \
79 ((xid) % (TransactionId) COMMIT_TS_XACTS_PER_PAGE)
80
81/*
82 * Link to shared-memory data structures for CommitTs control
83 */
84static void CommitTsShmemRequest(void *arg);
85static void CommitTsShmemInit(void *arg);
87static int commit_ts_errdetail_for_io_error(const void *opaque_data);
88
93
95
96#define CommitTsCtl (&CommitTsSlruDesc)
97
98/*
99 * We keep a cache of the last value set in shared memory.
100 *
101 * This is also good place to keep the activation status. We keep this
102 * separate from the GUC so that the standby can activate the module if the
103 * primary has it active independently of the value of the GUC.
104 *
105 * This is protected by CommitTsLock. In some places, we use commitTsActive
106 * without acquiring the lock; where this happens, a comment explains the
107 * rationale for it.
108 */
115
117
118static void CommitTsShmemInit(void *arg);
119
120/* GUC variable */
122
123static void SetXidCommitTsInPage(TransactionId xid, int nsubxids,
124 TransactionId *subxids, TimestampTz ts,
125 ReplOriginId nodeid, int64 pageno);
127 ReplOriginId nodeid, int slotno);
128static void error_commit_ts_disabled(void);
129static void ActivateCommitTs(void);
130static void DeactivateCommitTs(void);
131static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXid);
132
133/*
134 * TransactionTreeSetCommitTsData
135 *
136 * Record the final commit timestamp of transaction entries in the commit log
137 * for a transaction and its subtransaction tree, as efficiently as possible.
138 *
139 * xid is the top level transaction id.
140 *
141 * subxids is an array of xids of length nsubxids, representing subtransactions
142 * in the tree of xid. In various cases nsubxids may be zero.
143 * The reason why tracking just the parent xid commit timestamp is not enough
144 * is that the subtrans SLRU does not stay valid across crashes (it's not
145 * permanent) so we need to keep the information about them here. If the
146 * subtrans implementation changes in the future, we might want to revisit the
147 * decision of storing timestamp info for each subxid.
148 */
149void
152 ReplOriginId nodeid)
153{
154 int i;
157
158 /*
159 * No-op if the module is not active.
160 *
161 * An unlocked read here is fine, because in a standby (the only place
162 * where the flag can change in flight) this routine is only called by the
163 * recovery process, which is also the only process which can change the
164 * flag.
165 */
167 return;
168
169 /*
170 * Figure out the latest Xid in this batch: either the last subxid if
171 * there's any, otherwise the parent xid.
172 */
173 if (nsubxids > 0)
174 newestXact = subxids[nsubxids - 1];
175 else
176 newestXact = xid;
177
178 /*
179 * We split the xids to set the timestamp to in groups belonging to the
180 * same SLRU page; the first element in each such set is its head. The
181 * first group has the main XID as the head; subsequent sets use the first
182 * subxid not on the previous page as head. This way, we only have to
183 * lock/modify each SLRU page once.
184 */
185 headxid = xid;
186 i = 0;
187 for (;;)
188 {
190 int j;
191
192 for (j = i; j < nsubxids; j++)
193 {
194 if (TransactionIdToCTsPage(subxids[j]) != pageno)
195 break;
196 }
197 /* subxids[i..j] are on the same page as the head */
198
199 SetXidCommitTsInPage(headxid, j - i, subxids + i, timestamp, nodeid,
200 pageno);
201
202 /* if we wrote out all subxids, we're done. */
203 if (j >= nsubxids)
204 break;
205
206 /*
207 * Set the new head and skip over it, as well as over the subxids we
208 * just wrote.
209 */
210 headxid = subxids[j];
211 i = j + 1;
212 }
213
214 /* update the cached value in shared memory */
219
220 /* and move forwards our endpoint, if needed */
224}
225
226/*
227 * Record the commit timestamp of transaction entries in the commit log for all
228 * entries on a single page. Atomic only on this page.
229 */
230static void
232 TransactionId *subxids, TimestampTz ts,
233 ReplOriginId nodeid, int64 pageno)
234{
235 LWLock *lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
236 int slotno;
237 int i;
238
240
241 slotno = SimpleLruReadPage(CommitTsCtl, pageno, true, &xid);
242
243 TransactionIdSetCommitTs(xid, ts, nodeid, slotno);
244 for (i = 0; i < nsubxids; i++)
245 TransactionIdSetCommitTs(subxids[i], ts, nodeid, slotno);
246
247 CommitTsCtl->shared->page_dirty[slotno] = true;
248
249 LWLockRelease(lock);
250}
251
252/*
253 * Sets the commit timestamp of a single transaction.
254 *
255 * Caller must hold the correct SLRU bank lock, will be held at exit
256 */
257static void
259 ReplOriginId nodeid, int slotno)
260{
263
265
266 entry.time = ts;
267 entry.nodeid = nodeid;
268
269 memcpy(CommitTsCtl->shared->page_buffer[slotno] +
272}
273
274/*
275 * Interrogate the commit timestamp of a transaction.
276 *
277 * The return value indicates whether a commit timestamp record was found for
278 * the given xid. The timestamp value is returned in *ts (which may not be
279 * null), and the origin node for the Xid is returned in *nodeid, if it's not
280 * null.
281 */
282bool
284 ReplOriginId *nodeid)
285{
286 int64 pageno = TransactionIdToCTsPage(xid);
288 int slotno;
290 TransactionId oldestCommitTsXid;
291 TransactionId newestCommitTsXid;
292
293 if (!TransactionIdIsValid(xid))
296 errmsg("cannot retrieve commit timestamp for transaction %u", xid)));
297 else if (!TransactionIdIsNormal(xid))
298 {
299 /* frozen and bootstrap xids are always committed far in the past */
300 *ts = 0;
301 if (nodeid)
302 *nodeid = 0;
303 return false;
304 }
305
307
308 /* Error if module not enabled */
311
312 /*
313 * If we're asked for the cached value, return that. Otherwise, fall
314 * through to read from SLRU.
315 */
316 if (commitTsShared->xidLastCommit == xid)
317 {
319 if (nodeid)
321
323 return *ts != 0;
324 }
325
326 oldestCommitTsXid = TransamVariables->oldestCommitTsXid;
327 newestCommitTsXid = TransamVariables->newestCommitTsXid;
328 /* neither is invalid, or both are */
329 Assert(TransactionIdIsValid(oldestCommitTsXid) == TransactionIdIsValid(newestCommitTsXid));
331
332 /*
333 * Return empty if the requested value is outside our valid range.
334 */
335 if (!TransactionIdIsValid(oldestCommitTsXid) ||
336 TransactionIdPrecedes(xid, oldestCommitTsXid) ||
337 TransactionIdPrecedes(newestCommitTsXid, xid))
338 {
339 *ts = 0;
340 if (nodeid)
341 *nodeid = InvalidReplOriginId;
342 return false;
343 }
344
345 /* lock is acquired by SimpleLruReadPage_ReadOnly */
347 memcpy(&entry,
348 CommitTsCtl->shared->page_buffer[slotno] +
351
352 *ts = entry.time;
353 if (nodeid)
354 *nodeid = entry.nodeid;
355
357 return *ts != 0;
358}
359
360/*
361 * Return the Xid of the latest committed transaction. (As far as this module
362 * is concerned, anyway; it's up to the caller to ensure the value is useful
363 * for its purposes.)
364 *
365 * ts and nodeid are filled with the corresponding data; they can be passed
366 * as NULL if not wanted.
367 */
370{
371 TransactionId xid;
372
374
375 /* Error if module not enabled */
378
380 if (ts)
382 if (nodeid)
385
386 return xid;
387}
388
389static void
391{
394 errmsg("could not get commit timestamp data"),
396 errhint("Make sure the configuration parameter \"%s\" is set on the primary server.",
397 "track_commit_timestamp") :
398 errhint("Make sure the configuration parameter \"%s\" is set.",
399 "track_commit_timestamp")));
400}
401
402/*
403 * SQL-callable wrapper to obtain commit time of a transaction
404 */
405Datum
407{
409 TimestampTz ts;
410 bool found;
411
412 found = TransactionIdGetCommitTsData(xid, &ts, NULL);
413
414 if (!found)
416
418}
419
420
421/*
422 * pg_last_committed_xact
423 *
424 * SQL-callable wrapper to obtain some information about the latest
425 * committed transaction: transaction ID, timestamp and replication
426 * origin.
427 */
428Datum
430{
431 TransactionId xid;
432 ReplOriginId nodeid;
433 TimestampTz ts;
434 Datum values[3];
435 bool nulls[3];
436 TupleDesc tupdesc;
437 HeapTuple htup;
438
439 /* and construct a tuple with our data */
440 xid = GetLatestCommitTsData(&ts, &nodeid);
441
442 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
443 elog(ERROR, "return type must be a row type");
444
445 if (!TransactionIdIsNormal(xid))
446 {
447 memset(nulls, true, sizeof(nulls));
448 }
449 else
450 {
452 nulls[0] = false;
453
455 nulls[1] = false;
456
457 values[2] = ObjectIdGetDatum((Oid) nodeid);
458 nulls[2] = false;
459 }
460
461 htup = heap_form_tuple(tupdesc, values, nulls);
462
464}
465
466/*
467 * pg_xact_commit_timestamp_origin
468 *
469 * SQL-callable wrapper to obtain commit timestamp and replication origin
470 * of a given transaction.
471 */
472Datum
474{
476 ReplOriginId nodeid;
477 TimestampTz ts;
478 Datum values[2];
479 bool nulls[2];
480 TupleDesc tupdesc;
481 HeapTuple htup;
482 bool found;
483
484 found = TransactionIdGetCommitTsData(xid, &ts, &nodeid);
485
486 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
487 elog(ERROR, "return type must be a row type");
488
489 if (!found)
490 {
491 memset(nulls, true, sizeof(nulls));
492 }
493 else
494 {
496 nulls[0] = false;
497
498 values[1] = ObjectIdGetDatum((Oid) nodeid);
499 nulls[1] = false;
500 }
501
502 htup = heap_form_tuple(tupdesc, values, nulls);
503
505}
506
507/*
508 * Number of shared CommitTS buffers.
509 *
510 * If asked to autotune, use 2MB for every 1GB of shared buffers, up to 8MB.
511 * Otherwise just cap the configured amount to be between 16 and the maximum
512 * allowed.
513 */
514static int
516{
517 /* auto-tune based on shared buffers */
519 return SimpleLruAutotuneBuffers(512, 1024);
520
522}
523
524/*
525 * Register CommitTs shared memory needs at system startup (postmaster start
526 * or standalone backend)
527 */
528static void
530{
531 /* If auto-tuning is requested, now is the time to do it */
533 {
534 char buf[32];
535
536 snprintf(buf, sizeof(buf), "%d", CommitTsShmemBuffers());
537 SetConfigOption("commit_timestamp_buffers", buf, PGC_POSTMASTER,
539
540 /*
541 * We prefer to report this value's source as PGC_S_DYNAMIC_DEFAULT.
542 * However, if the DBA explicitly set commit_timestamp_buffers = 0 in
543 * the config file, then PGC_S_DYNAMIC_DEFAULT will fail to override
544 * that and we must force the matter with PGC_S_OVERRIDE.
545 */
546 if (commit_timestamp_buffers == 0) /* failed to apply it? */
547 SetConfigOption("commit_timestamp_buffers", buf, PGC_POSTMASTER,
549 }
552 .name = "commit_timestamp",
553 .Dir = "pg_commit_ts",
554 .long_segment_names = false,
555
556 .nslots = CommitTsShmemBuffers(),
557
558 .PagePrecedes = CommitTsPagePrecedes,
559 .errdetail_for_io_error = commit_ts_errdetail_for_io_error,
560
561 .sync_handler = SYNC_HANDLER_COMMIT_TS,
562 .buffer_tranche_id = LWTRANCHE_COMMITTS_BUFFER,
563 .bank_tranche_id = LWTRANCHE_COMMITTS_SLRU,
564 );
565
566 ShmemRequestStruct(.name = "CommitTs shared",
567 .size = sizeof(CommitTimestampShared),
568 .ptr = (void **) &commitTsShared,
569 );
570}
571
572static void
582
583/*
584 * GUC check_hook for commit_timestamp_buffers
585 */
586bool
588{
589 return check_slru_buffers("commit_timestamp_buffers", newval);
590}
591
592/*
593 * This function must be called ONCE on system install.
594 *
595 * (The CommitTs directory is assumed to have been created by initdb, and
596 * CommitTsShmemInit must have been called already.)
597 */
598void
600{
601 /*
602 * Nothing to do here at present, unlike most other SLRU modules; segments
603 * are created when the server is started with this module enabled. See
604 * ActivateCommitTs.
605 */
606}
607
608/*
609 * This must be called ONCE during postmaster or standalone-backend startup,
610 * after StartupXLOG has initialized TransamVariables->nextXid.
611 */
612void
614{
616}
617
618/*
619 * This must be called ONCE during postmaster or standalone-backend startup,
620 * after recovery has finished.
621 */
622void
624{
625 /*
626 * If the feature is not enabled, turn it off for good. This also removes
627 * any leftover data.
628 *
629 * Conversely, we activate the module if the feature is enabled. This is
630 * necessary for primary and standby as the activation depends on the
631 * control file contents at the beginning of recovery or when a
632 * XLOG_PARAMETER_CHANGE is replayed.
633 */
636 else
638}
639
640/*
641 * Activate or deactivate CommitTs' upon reception of a XLOG_PARAMETER_CHANGE
642 * XLog record during recovery.
643 */
644void
646{
647 /*
648 * If the commit_ts module is disabled in this server and we get word from
649 * the primary server that it is enabled there, activate it so that we can
650 * replay future WAL records involving it; also mark it as active on
651 * pg_control. If the old value was already set, we already did this, so
652 * don't do anything.
653 *
654 * If the module is disabled in the primary, disable it here too, unless
655 * the module is enabled locally.
656 *
657 * Note this only runs in the recovery process, so an unlocked read is
658 * fine.
659 */
660 if (newvalue)
661 {
664 }
667}
668
669/*
670 * Activate this module whenever necessary.
671 * This must happen during postmaster or standalone-backend startup,
672 * or during WAL replay anytime the track_commit_timestamp setting is
673 * changed in the primary.
674 *
675 * The reason why this SLRU needs separate activation/deactivation functions is
676 * that it can be enabled/disabled during start and the activation/deactivation
677 * on the primary is propagated to the standby via replay. Other SLRUs don't
678 * have this property and they can be just initialized during normal startup.
679 *
680 * This is in charge of creating the currently active segment, if it's not
681 * already there. The reason for this is that the server might have been
682 * running with this module disabled for a while and thus might have skipped
683 * the normal creation point.
684 */
685static void
687{
688 TransactionId xid;
689 int64 pageno;
690
691 /*
692 * During bootstrap, we should not register commit timestamps so skip the
693 * activation in this case.
694 */
696 return;
697
698 /* If we've done this already, there's nothing to do */
701 {
703 return;
704 }
706
708 pageno = TransactionIdToCTsPage(xid);
709
710 /*
711 * Re-Initialize our idea of the latest page number.
712 */
713 pg_atomic_write_u64(&CommitTsCtl->shared->latest_page_number, pageno);
714
715 /*
716 * If CommitTs is enabled, but it wasn't in the previous server run, we
717 * need to set the oldest and newest values to the next Xid; that way, we
718 * will not try to read data that might not have been set.
719 *
720 * XXX does this have a problem if a server is started with commitTs
721 * enabled, then started with commitTs disabled, then restarted with it
722 * enabled again? It doesn't look like it does, because there should be a
723 * checkpoint that sets the value to InvalidTransactionId at end of
724 * recovery; and so any chance of injecting new transactions without
725 * CommitTs values would occur after the oldestCommitTsXid has been set to
726 * Invalid temporarily.
727 */
730 {
733 }
735
736 /* Create the current segment file, if necessary */
739
740 /* Change the activation status in shared memory. */
744}
745
746/*
747 * Deactivate this module.
748 *
749 * This must be called when the track_commit_timestamp parameter is turned off.
750 * This happens during postmaster or standalone-backend startup, or during WAL
751 * replay.
752 *
753 * Resets CommitTs into invalid state to make sure we don't hand back
754 * possibly-invalid data; also removes segments of old data.
755 */
756static void
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 */
767
772
775
776 /*
777 * Remove *all* files. This is necessary so that there are no leftover
778 * files; in the case where this feature is later enabled after running
779 * with it disabled for some time there may be a gap in the file sequence.
780 * (We can probably tolerate out-of-sequence files, as they are going to
781 * be overwritten anyway when we wrap around, but it seems better to be
782 * tidy.)
783 *
784 * Note that we do this with CommitTsLock acquired in exclusive mode. This
785 * is very heavy-handed, but since this routine can only be called in the
786 * replica and should happen very rarely, we don't worry too much about
787 * it. Note also that no process should be consulting this SLRU if we
788 * have just deactivated it.
789 */
791
793}
794
795/*
796 * Perform a checkpoint --- either during shutdown, or on-the-fly
797 */
798void
800{
801 /*
802 * Write dirty CommitTs pages to disk. This may result in sync requests
803 * queued for later handling by ProcessSyncRequests(), as part of the
804 * checkpoint.
805 */
807}
808
809/*
810 * Make sure that CommitTs has room for a newly-allocated XID.
811 *
812 * NB: this is called while holding XidGenLock. We want it to be very fast
813 * most of the time; even when it's not so fast, no actual I/O need happen
814 * unless we're forced to write out a dirty CommitTs or xlog page to make room
815 * in shared memory.
816 *
817 * NB: the current implementation relies on track_commit_timestamp being
818 * PGC_POSTMASTER.
819 */
820void
822{
823 int64 pageno;
824 LWLock *lock;
825
826 /*
827 * Nothing to do if module not enabled. Note we do an unlocked read of
828 * the flag here, which is okay because this routine is only called from
829 * GetNewTransactionId, which is never called in a standby.
830 */
833 return;
834
835 /*
836 * No work except at first XID of a page. But beware: just after
837 * wraparound, the first XID of page zero is FirstNormalTransactionId.
838 */
841 return;
842
844
845 lock = SimpleLruGetBankLock(CommitTsCtl, pageno);
846
848
849 /* Zero the page ... */
851
852 /* and make a WAL entry about that, unless we're in REDO */
853 if (!InRecovery)
855
856 LWLockRelease(lock);
857}
858
859/*
860 * Remove all CommitTs segments before the one holding the passed
861 * transaction ID.
862 *
863 * Note that we don't need to flush XLOG here.
864 */
865void
867{
869
870 /*
871 * The cutoff point is the start of the segment containing oldestXact. We
872 * pass the *page* containing oldestXact to SimpleLruTruncate.
873 */
875
876 /* Check to see if there's any files that could be removed */
878 &cutoffPage))
879 return; /* nothing to remove */
880
881 /* Write XLOG record */
882 WriteTruncateXlogRec(cutoffPage, oldestXact);
883
884 /* Now we can remove the old CommitTs segment(s) */
886}
887
888/*
889 * Set the limit values between which commit TS can be consulted.
890 */
891void
893{
894 /*
895 * Be careful not to overwrite values that are either further into the
896 * "future" or signal a disabled committs.
897 */
900 {
905 }
906 else
907 {
911 }
913}
914
915/*
916 * Move forwards the oldest commitTS value that can be consulted
917 */
918void
927
928
929/*
930 * Decide whether a commitTS page number is "older" for truncation purposes.
931 * Analogous to CLOGPagePrecedes().
932 *
933 * At default BLCKSZ, (1 << 31) % COMMIT_TS_XACTS_PER_PAGE == 128. This
934 * introduces differences compared to CLOG and the other SLRUs having (1 <<
935 * 31) % per_page == 0. This function never tests exactly
936 * TransactionIdPrecedes(x-2^31, x). When the system reaches xidStopLimit,
937 * there are two possible counts of page boundaries between oldestXact and the
938 * latest XID assigned, depending on whether oldestXact is within the first
939 * 128 entries of its page. Since this function doesn't know the location of
940 * oldestXact within page2, it returns false for one page that actually is
941 * expendable. This is a wider (yet still negligible) version of the
942 * truncation opportunity that CLOGPagePrecedes() cannot recognize.
943 *
944 * For the sake of a worked example, number entries with decimal values such
945 * that page1==1 entries range from 1.0 to 1.999. Let N+0.15 be the number of
946 * pages that 2^31 entries will span (N is an integer). If oldestXact=N+2.1,
947 * then the final safe XID assignment leaves newestXact=1.95. We keep page 2,
948 * because entry=2.85 is the border that toggles whether entries precede the
949 * last entry of the oldestXact page. While page 2 is expendable at
950 * oldestXact=N+2.1, it would be precious at oldestXact=N+2.9.
951 */
952static bool
966
967static int
969{
970 TransactionId xid = *(const TransactionId *) opaque_data;
971
972 return errdetail("Could not access commit timestamp of transaction %u.", xid);
973}
974
975/*
976 * Write a TRUNCATE xlog record
977 */
978static void
990
991/*
992 * CommitTS resource manager's routines
993 */
994void
996{
997 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
998
999 /* Backup blocks are not used in commit_ts records */
1001
1002 if (info == COMMIT_TS_ZEROPAGE)
1003 {
1004 int64 pageno;
1005
1006 memcpy(&pageno, XLogRecGetData(record), sizeof(pageno));
1008 }
1009 else if (info == COMMIT_TS_TRUNCATE)
1010 {
1012
1013 AdvanceOldestCommitTsXid(trunc->oldestXid);
1014
1015 /*
1016 * During XLOG replay, latest_page_number isn't set up yet; insert a
1017 * suitable value to bypass the sanity test in SimpleLruTruncate.
1018 */
1019 pg_atomic_write_u64(&CommitTsCtl->shared->latest_page_number,
1020 trunc->pageno);
1021
1023 }
1024 else
1025 elog(PANIC, "commit_ts_redo: unknown op code %u", info);
1026}
1027
1028/*
1029 * Entrypoint for sync.c to sync commit_ts files.
1030 */
1031int
1032committssyncfiletag(const FileTag *ftag, char *path)
1033{
1034 return SlruSyncFileTag(CommitTsCtl, ftag, path);
1035}
static void pg_atomic_write_u64(volatile pg_atomic_uint64 *ptr, uint64 val)
Definition atomics.h:485
static Datum values[MAXATTR]
Definition bootstrap.c:190
#define Min(x, y)
Definition c.h:1091
uint8_t uint8
Definition c.h:622
#define Max(x, y)
Definition c.h:1085
#define Assert(condition)
Definition c.h:943
int64_t int64
Definition c.h:621
uint32 TransactionId
Definition c.h:736
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
static void SetXidCommitTsInPage(TransactionId xid, int nsubxids, TransactionId *subxids, TimestampTz ts, ReplOriginId nodeid, int64 pageno)
Definition commit_ts.c:231
void StartupCommitTs(void)
Definition commit_ts.c:613
Datum pg_xact_commit_timestamp_origin(PG_FUNCTION_ARGS)
Definition commit_ts.c:473
static int commit_ts_errdetail_for_io_error(const void *opaque_data)
Definition commit_ts.c:968
Datum pg_last_committed_xact(PG_FUNCTION_ARGS)
Definition commit_ts.c:429
static SlruDesc CommitTsSlruDesc
Definition commit_ts.c:94
void CommitTsParameterChange(bool newvalue, bool oldvalue)
Definition commit_ts.c:645
#define COMMIT_TS_XACTS_PER_PAGE
Definition commit_ts.c:64
#define TransactionIdToCTsEntry(xid)
Definition commit_ts.c:78
static void DeactivateCommitTs(void)
Definition commit_ts.c:757
bool track_commit_timestamp
Definition commit_ts.c:121
void AdvanceOldestCommitTsXid(TransactionId oldestXact)
Definition commit_ts.c:919
static void CommitTsShmemInit(void *arg)
Definition commit_ts.c:573
static CommitTimestampShared * commitTsShared
Definition commit_ts.c:116
int committssyncfiletag(const FileTag *ftag, char *path)
Definition commit_ts.c:1032
void CompleteCommitTsInitialization(void)
Definition commit_ts.c:623
void TransactionTreeSetCommitTsData(TransactionId xid, int nsubxids, TransactionId *subxids, TimestampTz timestamp, ReplOriginId nodeid)
Definition commit_ts.c:150
bool check_commit_ts_buffers(int *newval, void **extra, GucSource source)
Definition commit_ts.c:587
static void ActivateCommitTs(void)
Definition commit_ts.c:686
static int64 TransactionIdToCTsPage(TransactionId xid)
Definition commit_ts.c:73
void TruncateCommitTs(TransactionId oldestXact)
Definition commit_ts.c:866
void commit_ts_redo(XLogReaderState *record)
Definition commit_ts.c:995
Datum pg_xact_commit_timestamp(PG_FUNCTION_ARGS)
Definition commit_ts.c:406
static int CommitTsShmemBuffers(void)
Definition commit_ts.c:515
static void error_commit_ts_disabled(void)
Definition commit_ts.c:390
static bool CommitTsPagePrecedes(int64 page1, int64 page2)
Definition commit_ts.c:953
#define SizeOfCommitTimestampEntry
Definition commit_ts.c:61
void BootStrapCommitTs(void)
Definition commit_ts.c:599
void SetCommitTsLimit(TransactionId oldestXact, TransactionId newestXact)
Definition commit_ts.c:892
#define CommitTsCtl
Definition commit_ts.c:96
TransactionId GetLatestCommitTsData(TimestampTz *ts, ReplOriginId *nodeid)
Definition commit_ts.c:369
void ExtendCommitTs(TransactionId newestXact)
Definition commit_ts.c:821
bool TransactionIdGetCommitTsData(TransactionId xid, TimestampTz *ts, ReplOriginId *nodeid)
Definition commit_ts.c:283
static void CommitTsShmemRequest(void *arg)
Definition commit_ts.c:529
const ShmemCallbacks CommitTsShmemCallbacks
Definition commit_ts.c:89
static void TransactionIdSetCommitTs(TransactionId xid, TimestampTz ts, ReplOriginId nodeid, int slotno)
Definition commit_ts.c:258
static void WriteTruncateXlogRec(int64 pageno, TransactionId oldestXid)
Definition commit_ts.c:979
void CheckPointCommitTs(void)
Definition commit_ts.c:799
#define COMMIT_TS_ZEROPAGE
Definition commit_ts.h:44
#define SizeOfCommitTsTruncate
Definition commit_ts.h:53
#define COMMIT_TS_TRUNCATE
Definition commit_ts.h:45
int64 TimestampTz
Definition timestamp.h:39
#define TIMESTAMP_NOBEGIN(j)
Definition timestamp.h:159
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define PANIC
Definition elog.h:44
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
#define PG_RETURN_NULL()
Definition fmgr.h:346
#define PG_GETARG_TRANSACTIONID(n)
Definition fmgr.h:280
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition funcapi.h:230
int commit_timestamp_buffers
Definition globals.c:164
void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source)
Definition guc.c:4234
#define newval
GucSource
Definition guc.h:112
@ PGC_S_DYNAMIC_DEFAULT
Definition guc.h:114
@ PGC_S_OVERRIDE
Definition guc.h:123
@ PGC_POSTMASTER
Definition guc.h:74
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition heaptuple.c:1025
int j
Definition isn.c:78
int i
Definition isn.c:77
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_SHARED
Definition lwlock.h:105
@ LW_EXCLUSIVE
Definition lwlock.h:104
#define IsBootstrapProcessingMode()
Definition miscadmin.h:495
static char * errmsg
#define InvalidReplOriginId
Definition origin.h:33
static rewind_source * source
Definition pg_rewind.c:89
static char buf[DEFAULT_XLOG_SEG_SIZE]
int64 timestamp
#define snprintf
Definition port.h:260
static Datum TransactionIdGetDatum(TransactionId X)
Definition postgres.h:292
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
static int fb(int x)
#define ShmemRequestStruct(...)
Definition shmem.h:176
bool SlruScanDirectory(SlruDesc *ctl, SlruScanCallback callback, void *data)
Definition slru.c:1844
int SimpleLruReadPage_ReadOnly(SlruDesc *ctl, int64 pageno, const void *opaque_data)
Definition slru.c:654
int SimpleLruAutotuneBuffers(int divisor, int max)
Definition slru.c:235
bool SlruScanDirCbReportPresence(SlruDesc *ctl, char *filename, int64 segpage, void *data)
Definition slru.c:1765
void SimpleLruTruncate(SlruDesc *ctl, int64 cutoffPage)
Definition slru.c:1458
void SimpleLruZeroAndWritePage(SlruDesc *ctl, int64 pageno)
Definition slru.c:466
int SimpleLruZeroPage(SlruDesc *ctl, int64 pageno)
Definition slru.c:397
bool SimpleLruDoesPhysicalPageExist(SlruDesc *ctl, int64 pageno)
Definition slru.c:795
bool SlruScanDirCbDeleteAll(SlruDesc *ctl, char *filename, int64 segpage, void *data)
Definition slru.c:1797
void SimpleLruWriteAll(SlruDesc *ctl, bool allow_redirtied)
Definition slru.c:1372
int SimpleLruReadPage(SlruDesc *ctl, int64 pageno, bool write_ok, const void *opaque_data)
Definition slru.c:550
bool check_slru_buffers(const char *name, int *newval)
Definition slru.c:377
int SlruSyncFileTag(SlruDesc *ctl, const FileTag *ftag, char *path)
Definition slru.c:1884
#define SlruPagePrecedesUnitTests(ctl, per_page)
Definition slru.h:233
#define SimpleLruRequest(...)
Definition slru.h:218
#define SLRU_MAX_ALLOWED_BUFFERS
Definition slru.h:26
static LWLock * SimpleLruGetBankLock(SlruDesc *ctl, int64 pageno)
Definition slru.h:207
TimestampTz time
Definition commit_ts.c:57
ReplOriginId nodeid
Definition commit_ts.c:58
CommitTimestampEntry dataLastCommit
Definition commit_ts.c:112
TransactionId xidLastCommit
Definition commit_ts.c:111
Definition sync.h:51
ShmemRequestCallback request_fn
Definition shmem.h:133
TransactionId oldestCommitTsXid
Definition transam.h:232
TransactionId newestCommitTsXid
Definition transam.h:233
FullTransactionId nextXid
Definition transam.h:220
@ SYNC_HANDLER_COMMIT_TS
Definition sync.h:39
static TransactionId ReadNextTransactionId(void)
Definition transam.h:375
#define InvalidTransactionId
Definition transam.h:31
#define TransactionIdEquals(id1, id2)
Definition transam.h:43
#define XidFromFullTransactionId(x)
Definition transam.h:48
#define FirstNormalTransactionId
Definition transam.h:34
#define TransactionIdIsValid(xid)
Definition transam.h:41
#define TransactionIdIsNormal(xid)
Definition transam.h:42
static bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition transam.h:263
static Datum TimestampTzGetDatum(TimestampTz X)
Definition timestamp.h:52
#define PG_RETURN_TIMESTAMPTZ(x)
Definition timestamp.h:68
TransamVariablesData * TransamVariables
Definition varsup.c:37
const char * name
bool RecoveryInProgress(void)
Definition xlog.c:6830
uint16 ReplOriginId
Definition xlogdefs.h:69
XLogRecPtr XLogSimpleInsertInt64(RmgrId rmid, uint8 info, int64 value)
Definition xloginsert.c:547
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition xloginsert.c:482
void XLogRegisterData(const void *data, uint32 len)
Definition xloginsert.c:372
void XLogBeginInsert(void)
Definition xloginsert.c:153
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:410
#define XLogRecGetData(decoder)
Definition xlogreader.h:415
#define XLogRecHasAnyBlockRefs(decoder)
Definition xlogreader.h:417
bool InRecovery
Definition xlogutils.c:50