PostgreSQL Source Code git master
Loading...
Searching...
No Matches
walsummarizer.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * walsummarizer.c
4 *
5 * Background process to perform WAL summarization, if it is enabled.
6 * It continuously scans the write-ahead log and periodically emits a
7 * summary file which indicates which blocks in which relation forks
8 * were modified by WAL records in the LSN range covered by the summary
9 * file. See walsummary.c and blkreftable.c for more details on the
10 * naming and contents of WAL summary files.
11 *
12 * If configured to do, this background process will also remove WAL
13 * summary files when the file timestamp is older than a configurable
14 * threshold (but only if the WAL has been removed first).
15 *
16 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
17 *
18 * IDENTIFICATION
19 * src/backend/postmaster/walsummarizer.c
20 *
21 *-------------------------------------------------------------------------
22 */
23#include "postgres.h"
24
25#include "access/timeline.h"
27#include "access/xlog.h"
29#include "access/xlogrecovery.h"
30#include "access/xlogutils.h"
31#include "backup/walsummary.h"
34#include "common/blkreftable.h"
35#include "libpq/pqsignal.h"
36#include "miscadmin.h"
37#include "pgstat.h"
42#include "storage/aio_subsys.h"
43#include "storage/fd.h"
44#include "storage/ipc.h"
45#include "storage/latch.h"
46#include "storage/lwlock.h"
47#include "storage/proc.h"
48#include "storage/procsignal.h"
49#include "storage/shmem.h"
50#include "storage/subsystems.h"
51#include "utils/guc.h"
52#include "utils/memutils.h"
53#include "utils/wait_event.h"
54
55/*
56 * Data in shared memory related to WAL summarization.
57 */
58typedef struct
59{
60 /*
61 * These fields are protected by WALSummarizerLock.
62 *
63 * Until we've discovered what summary files already exist on disk and
64 * stored that information in shared memory, initialized is false and the
65 * other fields here contain no meaningful information. After that has
66 * been done, initialized is true.
67 *
68 * summarized_tli and summarized_lsn indicate the last LSN and TLI at
69 * which the next summary file will start. Normally, these are the LSN and
70 * TLI at which the last file ended; in such case, lsn_is_exact is true.
71 * If, however, the LSN is just an approximation, then lsn_is_exact is
72 * false. This can happen if, for example, there are no existing WAL
73 * summary files at startup. In that case, we have to derive the position
74 * at which to start summarizing from the WAL files that exist on disk,
75 * and so the LSN might point to the start of the next file even though
76 * that might happen to be in the middle of a WAL record.
77 *
78 * summarizer_pgprocno is the proc number of the summarizer process, if
79 * one is running, or else INVALID_PROC_NUMBER.
80 *
81 * pending_lsn is used by the summarizer to advertise the ending LSN of a
82 * record it has recently read. It shouldn't ever be less than
83 * summarized_lsn, but might be greater, because the summarizer buffers
84 * data for a range of LSNs in memory before writing out a new file.
85 */
92
93 /*
94 * This field handles its own synchronization.
95 */
98
99/*
100 * Private data for our xlogreader's page read callback.
101 */
109
110/* Pointer to shared memory state. */
112
113static void WalSummarizerShmemRequest(void *arg);
114static void WalSummarizerShmemInit(void *arg);
115
120
121/*
122 * When we reach end of WAL and need to read more, we sleep for a number of
123 * milliseconds that is an integer multiple of MS_PER_SLEEP_QUANTUM. This is
124 * the multiplier. It should vary between 1 and MAX_SLEEP_QUANTA, depending
125 * on system activity. See summarizer_wait_for_wal() for how we adjust this.
126 */
127static long sleep_quanta = 1;
128
129/*
130 * The sleep time will always be a multiple of 200ms and will not exceed
131 * thirty seconds (150 * 200 = 30 * 1000). Note that the timeout here needs
132 * to be substantially less than the maximum amount of time for which an
133 * incremental backup will wait for this process to catch up. Otherwise, an
134 * incremental backup might time out on an idle system just because we sleep
135 * for too long.
136 */
137#define MAX_SLEEP_QUANTA 150
138#define MS_PER_SLEEP_QUANTUM 200
139
140/*
141 * This is a count of the number of pages of WAL that we've read since the
142 * last time we waited for more WAL to appear.
143 */
145
146/*
147 * Most recent RedoRecPtr value observed by MaybeRemoveOldWalSummaries.
148 */
150
151/*
152 * GUC parameters
153 */
154bool summarize_wal = false;
156
157static void WalSummarizerShutdown(int code, Datum arg);
159static void ProcessWalSummarizerInterrupts(void);
160static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn,
164 BlockRefTable *brtab);
166 BlockRefTable *brtab);
168 BlockRefTable *brtab);
170 bool *new_fast_forward);
173 int reqLen,
175 char *cur_page);
176static void summarizer_wait_for_wal(void);
177static void MaybeRemoveOldWalSummaries(void);
178
179/*
180 * Register shared memory space needed by this module.
181 */
182static void
184{
185 ShmemRequestStruct(.name = "Wal Summarizer Ctl",
186 .size = sizeof(WalSummarizerData),
187 .ptr = (void **) &WalSummarizerCtl,
188 );
189}
190
191/*
192 * Initialize shared memory for this module.
193 */
194static void
196{
197 /*
198 * We're just filling in dummy values here -- the real initialization will
199 * happen when GetOldestUnsummarizedLSN() is called for the first time.
200 */
208}
209
210/*
211 * Entry point for walsummarizer process.
212 */
213void
215{
217 MemoryContext context;
218
219 /*
220 * Within this function, 'current_lsn' and 'current_tli' refer to the
221 * point from which the next WAL summary file should start. 'exact' is
222 * true if 'current_lsn' is known to be the start of a WAL record or WAL
223 * segment, and false if it might be in the middle of a record someplace.
224 *
225 * 'switch_lsn' and 'switch_tli', if set, are the LSN at which we need to
226 * switch to a new timeline and the timeline to which we need to switch.
227 * If not set, we either haven't figured out the answers yet or we're
228 * already on the latest timeline.
229 */
232 bool exact;
235
237
239
241 (errmsg_internal("WAL summarizer started")));
242
243 /*
244 * Properly accept or ignore signals the postmaster might send us
245 */
247 pqsignal(SIGINT, PG_SIG_IGN); /* no query to cancel */
249 /* SIGQUIT handler was already set up by InitPostmasterChild */
253 pqsignal(SIGUSR2, PG_SIG_IGN); /* not used */
254
255 /* Advertise ourselves. */
260
261 /* Create and switch to a memory context that we can reset on error. */
263 "Wal Summarizer",
265 MemoryContextSwitchTo(context);
266
267 /*
268 * Reset some signals that are accepted by postmaster but not here
269 */
271
272 /*
273 * If an exception is encountered, processing resumes here.
274 */
275 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
276 {
277 /* Since not using PG_TRY, must reset error stack by hand */
279
280 /* Prevent interrupts while cleaning up */
282
283 /* Report the error to the server log */
285
286 /* Release resources we might have acquired. */
292 AtEOXact_Files(false);
293 AtEOXact_HashTables(false);
294
295 /*
296 * Now return to normal top-level context and clear ErrorContext for
297 * next time.
298 */
299 MemoryContextSwitchTo(context);
301
302 /* Flush any leaked data in the top-level context */
303 MemoryContextReset(context);
304
305 /* Now we can allow interrupts again */
307
308 /*
309 * Sleep for 10 seconds before attempting to resume operations in
310 * order to avoid excessive logging.
311 *
312 * Many of the likely error conditions are things that will repeat
313 * every time. For example, if the WAL can't be read or the summary
314 * can't be written, only administrator action will cure the problem.
315 * So a really fast retry time doesn't seem to be especially
316 * beneficial, and it will clutter the logs.
317 */
320 10000,
322 }
323
324 /* We can now handle ereport(ERROR) */
326
327 /*
328 * Unblock signals (they were blocked when the postmaster forked us)
329 */
331
332 /*
333 * Fetch information about previous progress from shared memory, and ask
334 * GetOldestUnsummarizedLSN to reset pending_lsn to summarized_lsn. We
335 * might be recovering from an error, and if so, pending_lsn might have
336 * advanced past summarized_lsn, but any WAL we read previously has been
337 * lost and will need to be reread.
338 *
339 * If we discover that WAL summarization is not enabled, just exit.
340 */
343 proc_exit(0);
344
345 /*
346 * Loop forever
347 */
348 for (;;)
349 {
354
355 /* Flush any leaked data in the top-level context */
356 MemoryContextReset(context);
357
358 /* Process any signals received recently. */
360
361 /* If it's time to remove any old WAL summaries, do that now. */
363
364 /* Find the LSN and TLI up to which we can safely summarize. */
366
367 /*
368 * If we're summarizing a historic timeline and we haven't yet
369 * computed the point at which to switch to the next timeline, do that
370 * now.
371 *
372 * Note that if this is a standby, what was previously the current
373 * timeline could become historic at any time.
374 *
375 * We could try to make this more efficient by caching the results of
376 * readTimeLineHistory when latest_tli has not changed, but since we
377 * only have to do this once per timeline switch, we probably wouldn't
378 * save any significant amount of work in practice.
379 */
381 {
383
386 errmsg_internal("switch point from TLI %u to TLI %u is at %X/%08X",
388 }
389
390 /*
391 * If we've reached the switch LSN, we can't summarize anything else
392 * on this timeline. Switch to the next timeline and go around again,
393 * backing up to the exact switch point if we passed it.
394 */
396 {
397 /* Restart summarization from switch point. */
400
401 /* Next timeline and switch point, if any, not yet known. */
403 switch_tli = 0;
404
405 /* Update (really, rewind, if needed) state in shared memory. */
412
413 continue;
414 }
415
416 /* Summarize WAL. */
423
424 /*
425 * Update state for next loop iteration.
426 *
427 * Next summary file should start from exactly where this one ended.
428 */
430 exact = true;
431
432 /* Update state in shared memory. */
439
440 /* Wake up anyone waiting for more summary files to be written. */
442 }
443}
444
445/*
446 * Get information about the state of the WAL summarizer.
447 */
448void
449GetWalSummarizerState(TimeLineID *summarized_tli, XLogRecPtr *summarized_lsn,
450 XLogRecPtr *pending_lsn, int *summarizer_pid)
451{
454 {
455 /*
456 * If initialized is false, the rest of the structure contents are
457 * undefined.
458 */
459 *summarized_tli = 0;
460 *summarized_lsn = InvalidXLogRecPtr;
461 *pending_lsn = InvalidXLogRecPtr;
462 *summarizer_pid = -1;
463 }
464 else
465 {
466 int summarizer_pgprocno = WalSummarizerCtl->summarizer_pgprocno;
467
468 *summarized_tli = WalSummarizerCtl->summarized_tli;
469 *summarized_lsn = WalSummarizerCtl->summarized_lsn;
470 if (summarizer_pgprocno == INVALID_PROC_NUMBER)
471 {
472 /*
473 * If the summarizer has exited, the fact that it had processed
474 * beyond summarized_lsn is irrelevant now.
475 */
476 *pending_lsn = WalSummarizerCtl->summarized_lsn;
477 *summarizer_pid = -1;
478 }
479 else
480 {
481 *pending_lsn = WalSummarizerCtl->pending_lsn;
482
483 /*
484 * We're not fussed about inexact answers here, since they could
485 * become stale instantly, so we don't bother taking the lock, but
486 * make sure that invalid PID values are normalized to -1.
487 */
488 *summarizer_pid = GetPGProcByNumber(summarizer_pgprocno)->pid;
489 if (*summarizer_pid <= 0)
490 *summarizer_pid = -1;
491 }
492 }
494}
495
496/*
497 * Get the oldest LSN in this server's timeline history that has not yet been
498 * summarized, and update shared memory state as appropriate.
499 *
500 * If *tli != NULL, it will be set to the TLI for the LSN that is returned.
501 *
502 * If *lsn_is_exact != NULL, it will be set to true if the returned LSN is
503 * necessarily the start of a WAL record and false if it's just the beginning
504 * of a WAL segment.
505 */
507GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact)
508{
510 int n;
511 List *tles;
514 bool should_make_exact = false;
516 ListCell *lc;
518
519 /* If not summarizing WAL, do nothing. */
520 if (!summarize_wal)
521 return InvalidXLogRecPtr;
522
523 /*
524 * If we are not the WAL summarizer process, then we normally just want to
525 * read the values from shared memory. However, as an exception, if shared
526 * memory hasn't been initialized yet, then we need to do that so that we
527 * can read legal values and not remove any WAL too early.
528 */
530 {
532
534 {
536 if (tli != NULL)
538 if (lsn_is_exact != NULL)
539 *lsn_is_exact = WalSummarizerCtl->lsn_is_exact;
541 return unsummarized_lsn;
542 }
543
545 }
546
547 /*
548 * Find the oldest timeline on which WAL still exists, and the earliest
549 * segment for which it exists.
550 *
551 * Note that we do this every time the WAL summarizer process restarts or
552 * recovers from an error, in case the contents of pg_wal have changed
553 * under us e.g. if some files were removed, either manually - which
554 * shouldn't really happen, but might - or by postgres itself, if
555 * summarize_wal was turned off and then back on again.
556 */
559 for (n = list_length(tles) - 1; n >= 0; --n)
560 {
563
565 if (oldest_segno != 0)
566 {
567 /* Compute oldest LSN that still exists on disk. */
570
571 unsummarized_tli = tle->tli;
572 break;
573 }
574 }
575
576 /*
577 * Don't try to summarize anything older than the end LSN of the newest
578 * summary file that exists for this timeline.
579 */
583 foreach(lc, existing_summaries)
584 {
586
587 if (ws->end_lsn > unsummarized_lsn)
588 {
589 unsummarized_lsn = ws->end_lsn;
590 should_make_exact = true;
591 }
592 }
593
594 /* It really should not be possible for us to find no WAL. */
595 if (unsummarized_tli == 0)
598 errmsg_internal("no WAL found on timeline %u", latest_tli));
599
600 /*
601 * If we're the WAL summarizer, we always want to store the values we just
602 * computed into shared memory, because those are the values we're going
603 * to use to drive our operation, and so they are the authoritative
604 * values. Otherwise, we only store values into shared memory if shared
605 * memory is uninitialized. Our values are not canonical in such a case,
606 * but it's better to have something than nothing, to guide WAL retention.
607 */
610 {
616 }
617 else
619
620 /* Also return the to the caller as required. */
621 if (tli != NULL)
623 if (lsn_is_exact != NULL)
624 *lsn_is_exact = WalSummarizerCtl->lsn_is_exact;
626
627 return unsummarized_lsn;
628}
629
630/*
631 * Wake up the WAL summarizer process.
632 *
633 * This might not work, because there's no guarantee that the WAL summarizer
634 * process was successfully started, and it also might have started but
635 * subsequently terminated. So, under normal circumstances, this will get the
636 * latch set, but there's no guarantee.
637 */
638void
640{
641 ProcNumber pgprocno;
642
643 if (WalSummarizerCtl == NULL)
644 return;
645
649
650 if (pgprocno != INVALID_PROC_NUMBER)
651 SetLatch(&GetPGProcByNumber(pgprocno)->procLatch);
652}
653
654/*
655 * Wait until WAL summarization reaches the given LSN, but time out with an
656 * error if the summarizer seems to be stick.
657 *
658 * Returns immediately if summarize_wal is turned off while we wait. Caller
659 * is expected to handle this case, if necessary.
660 */
661void
663{
668 int deadcycles = 0;
669
671
672 while (1)
673 {
674 long timeout_in_ms = 10000;
675 XLogRecPtr summarized_lsn;
676 XLogRecPtr pending_lsn;
677
679
680 /* If WAL summarization is disabled while we're waiting, give up. */
681 if (!summarize_wal)
682 return;
683
684 /*
685 * If the LSN summarized on disk has reached the target value, stop.
686 */
688 summarized_lsn = WalSummarizerCtl->summarized_lsn;
689 pending_lsn = WalSummarizerCtl->pending_lsn;
691
692 /* If WAL summarization has progressed sufficiently, stop waiting. */
693 if (summarized_lsn >= lsn)
694 break;
695
696 /* Recheck current time. */
698
699 /* Have we finished the current cycle of waiting? */
702 {
703 long elapsed_seconds;
704
705 /* Begin new wait cycle. */
708
709 /*
710 * Keep track of the number of cycles during which there has been
711 * no progression of pending_lsn. If pending_lsn is not advancing,
712 * that means that not only are no new files appearing on disk,
713 * but we're not even incorporating new records into the in-memory
714 * state.
715 */
716 if (pending_lsn > prior_pending_lsn)
717 {
718 prior_pending_lsn = pending_lsn;
719 deadcycles = 0;
720 }
721 else
722 ++deadcycles;
723
724 /*
725 * If we've managed to wait for an entire minute without the WAL
726 * summarizer absorbing a single WAL record, error out; probably
727 * something is wrong.
728 *
729 * We could consider also erroring out if the summarizer is taking
730 * too long to catch up, but it's not clear what rate of progress
731 * would be acceptable and what would be too slow. So instead, we
732 * just try to error out in the case where there's no progress at
733 * all. That seems likely to catch a reasonable number of the
734 * things that can go wrong in practice (e.g. the summarizer
735 * process is completely hung, say because somebody hooked up a
736 * debugger to it or something) without giving up too quickly when
737 * the system is just slow.
738 */
739 if (deadcycles >= 6)
742 errmsg("WAL summarization is not progressing"),
743 errdetail("Summarization is needed through %X/%08X, but is stuck at %X/%08X on disk and %X/%08X in memory.",
744 LSN_FORMAT_ARGS(lsn),
745 LSN_FORMAT_ARGS(summarized_lsn),
746 LSN_FORMAT_ARGS(pending_lsn))));
747
748
749 /*
750 * Otherwise, just let the user know what's happening.
751 */
754 current_time) / 1000;
757 errmsg_plural("still waiting for WAL summarization through %X/%08X after %ld second",
758 "still waiting for WAL summarization through %X/%08X after %ld seconds",
760 LSN_FORMAT_ARGS(lsn),
762 errdetail("Summarization has reached %X/%08X on disk and %X/%08X in memory.",
763 LSN_FORMAT_ARGS(summarized_lsn),
764 LSN_FORMAT_ARGS(pending_lsn))));
765 }
766
767 /*
768 * Align the wait time to prevent drift. This doesn't really matter,
769 * but we'd like the warnings about how long we've been waiting to say
770 * 10 seconds, 20 seconds, 30 seconds, 40 seconds ... without ever
771 * drifting to something that is not a multiple of ten.
772 */
775
776 /* Wait and see. */
780 }
781
783}
784
785/*
786 * On exit, update shared memory to make it clear that we're no longer
787 * running.
788 */
789static void
796
797/*
798 * Get the latest LSN that is eligible to be summarized, and set *tli to the
799 * corresponding timeline.
800 */
801static XLogRecPtr
803{
804 if (!RecoveryInProgress())
805 {
806 /* Don't summarize WAL before it's flushed. */
807 return GetFlushRecPtr(tli);
808 }
809 else
810 {
816
817 /*
818 * After the insert TLI has been set and before the control file has
819 * been updated to show the DB in production, RecoveryInProgress()
820 * will return true, because it's not yet safe for all backends to
821 * begin writing WAL. However, replay has already ceased, so from our
822 * point of view, recovery is already over. We should summarize up to
823 * where replay stopped and then prepare to resume at the start of the
824 * insert timeline.
825 */
827 {
828 *tli = insert_tli;
830 }
831
832 /*
833 * What we really want to know is how much WAL has been flushed to
834 * disk, but the only flush position available is the one provided by
835 * the walreceiver, which may not be running, because this could be
836 * crash recovery or recovery via restore_command. So use either the
837 * WAL receiver's flush position or the replay position, whichever is
838 * further ahead, on the theory that if the WAL has been replayed then
839 * it must also have been flushed to disk.
840 */
843 if (flush_lsn > replay_lsn)
844 {
845 *tli = flush_tli;
846 return flush_lsn;
847 }
848 else
849 {
850 *tli = replay_tli;
851 return replay_lsn;
852 }
853 }
854}
855
856/*
857 * Interrupt handler for main loop of WAL summarizer process.
858 */
859static void
861{
864
866 {
867 ConfigReloadPending = false;
869 }
870
872 {
874 errmsg_internal("WAL summarizer shutting down"));
875 proc_exit(0);
876 }
877
878 /* Perform logging of memory contexts of this process */
881}
882
883/*
884 * Summarize a range of WAL records on a single timeline.
885 *
886 * 'tli' is the timeline to be summarized.
887 *
888 * 'start_lsn' is the point at which we should start summarizing. If this
889 * value comes from the end LSN of the previous record as returned by the
890 * xlogreader machinery, 'exact' should be true; otherwise, 'exact' should
891 * be false, and this function will search forward for the start of a valid
892 * WAL record.
893 *
894 * 'switch_lsn' is the point at which we should switch to a later timeline,
895 * if we're summarizing a historic timeline.
896 *
897 * 'maximum_lsn' identifies the point beyond which we can't count on being
898 * able to read any more WAL. It should be the switch point when reading a
899 * historic timeline, or the most-recently-measured end of WAL when reading
900 * the current timeline.
901 *
902 * The return value is the LSN at which the WAL summary actually ends. Most
903 * often, a summary file ends because we notice that a checkpoint has
904 * occurred and reach the redo pointer of that checkpoint, but sometimes
905 * we stop for other reasons, such as a timeline switch.
906 */
907static XLogRecPtr
910{
911 SummarizerReadLocalXLogPrivate *private_data;
915 char temp_path[MAXPGPATH];
916 char final_path[MAXPGPATH];
917 WalSummaryIO io;
919 bool fast_forward = true;
920 char *errormsg;
921
922 /* Initialize private data for xlogreader. */
924 private_data->tli = tli;
925 private_data->historic = XLogRecPtrIsValid(switch_lsn);
926 private_data->read_upto = maximum_lsn;
927
928 /* Create xlogreader. */
931 .segment_open = &wal_segment_open,
932 .segment_close = &wal_segment_close),
933 private_data);
934 if (xlogreader == NULL)
937 errmsg("out of memory"),
938 errdetail("Failed while allocating a WAL reading processor.")));
939
940 /*
941 * When exact = false, we're starting from an arbitrary point in the WAL
942 * and must search forward for the start of the next record.
943 *
944 * When exact = true, start_lsn should be either the LSN where a record
945 * begins, or the LSN of a page where the page header is immediately
946 * followed by the start of a new record. XLogBeginRead should tolerate
947 * either case.
948 *
949 * We need to allow for both cases because the behavior of xlogreader
950 * varies. When a record spans two or more xlog pages, the ending LSN
951 * reported by xlogreader will be the starting LSN of the following
952 * record, but when an xlog page boundary falls between two records, the
953 * end LSN for the first will be reported as the first byte of the
954 * following page. We can't know until we read that page how large the
955 * header will be, but we'll have to skip over it to find the next record.
956 */
957 if (exact)
958 {
959 /*
960 * Even if start_lsn is the beginning of a page rather than the
961 * beginning of the first record on that page, we should still use it
962 * as the start LSN for the summary file. That's because we detect
963 * missing summary files by looking for cases where the end LSN of one
964 * file is less than the start LSN of the next file. When only a page
965 * header is skipped, nothing has been missed.
966 */
967 XLogBeginRead(xlogreader, start_lsn);
968 summary_start_lsn = start_lsn;
969 }
970 else
971 {
972 summary_start_lsn = XLogFindNextRecord(xlogreader, start_lsn, &errormsg);
974 {
975 /*
976 * If we hit end-of-WAL while trying to find the next valid
977 * record, we must be on a historic timeline that has no valid
978 * records that begin after start_lsn and before end of WAL.
979 */
980 if (private_data->end_of_wal)
981 {
983 errmsg_internal("could not read WAL from timeline %u at %X/%08X: end of WAL at %X/%08X",
984 tli,
985 LSN_FORMAT_ARGS(start_lsn),
986 LSN_FORMAT_ARGS(private_data->read_upto)));
987
988 /*
989 * The timeline ends at or after start_lsn, without containing
990 * any records. Thus, we must make sure the main loop does not
991 * iterate. If start_lsn is the end of the timeline, then we
992 * won't actually emit an empty summary file, but otherwise,
993 * we must, to capture the fact that the LSN range in question
994 * contains no interesting WAL records.
995 */
996 summary_start_lsn = start_lsn;
997 summary_end_lsn = private_data->read_upto;
999 }
1000 else
1001 {
1002 if (errormsg)
1003 ereport(ERROR,
1004 errmsg("could not find a valid record after %X/%08X: %s",
1005 LSN_FORMAT_ARGS(start_lsn), errormsg));
1006 else
1007 ereport(ERROR,
1008 errmsg("could not find a valid record after %X/%08X",
1009 LSN_FORMAT_ARGS(start_lsn)));
1010 }
1011 }
1012
1013 /* We shouldn't go backward. */
1014 Assert(summary_start_lsn >= start_lsn);
1015 }
1016
1017 /*
1018 * Main loop: read xlog records one by one.
1019 */
1020 while (1)
1021 {
1022 int block_id;
1023 XLogRecord *record;
1024 uint8 rmid;
1025
1027
1028 /* We shouldn't go backward. */
1030
1031 /* Now read the next record. */
1032 record = XLogReadRecord(xlogreader, &errormsg);
1033 if (record == NULL)
1034 {
1035 if (private_data->end_of_wal)
1036 {
1037 /*
1038 * This timeline must be historic and must end before we were
1039 * able to read a complete record.
1040 */
1042 errmsg_internal("could not read WAL from timeline %u at %X/%08X: end of WAL at %X/%08X",
1043 tli,
1045 LSN_FORMAT_ARGS(private_data->read_upto)));
1046 /* Summary ends at end of WAL. */
1047 summary_end_lsn = private_data->read_upto;
1048 break;
1049 }
1050 if (errormsg)
1051 ereport(ERROR,
1053 errmsg("could not read WAL from timeline %u at %X/%08X: %s",
1055 errormsg)));
1056 else
1057 ereport(ERROR,
1059 errmsg("could not read WAL from timeline %u at %X/%08X",
1061 }
1062
1063 /* We shouldn't go backward. */
1065
1068 {
1069 /*
1070 * Whoops! We've read a record that *starts* after the switch LSN,
1071 * contrary to our goal of reading only until we hit the first
1072 * record that ends at or after the switch LSN. Pretend we didn't
1073 * read it after all by bailing out of this loop right here,
1074 * before we do anything with this record.
1075 *
1076 * This can happen because the last record before the switch LSN
1077 * might be continued across multiple pages, and then we might
1078 * come to a page with XLP_FIRST_IS_OVERWRITE_CONTRECORD set. In
1079 * that case, the record that was continued across multiple pages
1080 * is incomplete and will be disregarded, and the read will
1081 * restart from the beginning of the page that is flagged
1082 * XLP_FIRST_IS_OVERWRITE_CONTRECORD.
1083 *
1084 * If this case occurs, we can fairly say that the current summary
1085 * file ends at the switch LSN exactly. The first record on the
1086 * page marked XLP_FIRST_IS_OVERWRITE_CONTRECORD will be
1087 * discovered when generating the next summary file.
1088 */
1090 break;
1091 }
1092
1093 /*
1094 * Certain types of records require special handling. Redo points and
1095 * shutdown checkpoints trigger creation of new summary files and can
1096 * also cause us to enter or exit "fast forward" mode. Other types of
1097 * records can require special updates to the block reference table.
1098 */
1099 rmid = XLogRecGetRmid(xlogreader);
1100 if (rmid == RM_XLOG_ID)
1101 {
1102 bool new_fast_forward;
1103
1104 /*
1105 * If we've already processed some WAL records when we hit a redo
1106 * point or shutdown checkpoint, then we stop summarization before
1107 * including this record in the current file, so that it will be
1108 * the first record in the next file.
1109 *
1110 * When we hit one of those record types as the first record in a
1111 * file, we adjust our notion of whether we're fast-forwarding.
1112 * Any WAL generated with wal_level=minimal must be skipped
1113 * without actually generating any summary file, because an
1114 * incremental backup that crosses such WAL would be unsafe.
1115 */
1117 {
1119 {
1121 break;
1122 }
1123 else
1124 fast_forward = new_fast_forward;
1125 }
1126 }
1127 else if (!fast_forward)
1128 {
1129 /*
1130 * This switch handles record types that require extra updates to
1131 * the contents of the block reference table.
1132 */
1133 switch (rmid)
1134 {
1135 case RM_DBASE_ID:
1137 break;
1138 case RM_SMGR_ID:
1140 break;
1141 case RM_XACT_ID:
1143 break;
1144 }
1145 }
1146
1147 /*
1148 * If we're in fast-forward mode, we don't really need to do anything.
1149 * Otherwise, feed block references from xlog record to block
1150 * reference table.
1151 */
1152 if (!fast_forward)
1153 {
1155 block_id++)
1156 {
1157 RelFileLocator rlocator;
1158 ForkNumber forknum;
1159 BlockNumber blocknum;
1160
1162 &forknum, &blocknum, NULL))
1163 continue;
1164
1165 /*
1166 * As we do elsewhere, ignore the FSM fork, because it's not
1167 * fully WAL-logged.
1168 */
1169 if (forknum != FSM_FORKNUM)
1170 BlockRefTableMarkBlockModified(brtab, &rlocator, forknum,
1171 blocknum);
1172 }
1173 }
1174
1175 /* Update our notion of where this summary file ends. */
1177
1178 /* Also update shared memory. */
1183
1184 /*
1185 * If we have a switch LSN and have reached it, stop before reading
1186 * the next record.
1187 */
1190 break;
1191 }
1192
1193 /* Destroy xlogreader. */
1196
1197 /*
1198 * If a timeline switch occurs, we may fail to make any progress at all
1199 * before exiting the loop above. If that happens, we don't write a WAL
1200 * summary file at all. We can also skip writing a file if we're in
1201 * fast-forward mode.
1202 */
1203 if (summary_end_lsn > summary_start_lsn && !fast_forward)
1204 {
1205 /* Generate temporary and final path name. */
1207 XLOGDIR "/summaries/temp.summary");
1209 XLOGDIR "/summaries/%08X%08X%08X%08X%08X.summary",
1210 tli,
1213
1214 /* Open the temporary file for writing. */
1215 io.filepos = 0;
1217 if (io.file < 0)
1218 ereport(ERROR,
1220 errmsg("could not create file \"%s\": %m", temp_path)));
1221
1222 /* Write the data. */
1224
1225 /* Close temporary file and shut down xlogreader. */
1226 FileClose(io.file);
1227
1228 /* Tell the user what we did. */
1230 errmsg_internal("summarized WAL on TLI %u from %X/%08X to %X/%08X",
1231 tli,
1234
1235 /* Durably rename the new summary into place. */
1237 }
1238
1239 /* If we skipped a non-zero amount of WAL, log a debug message. */
1240 if (summary_end_lsn > summary_start_lsn && fast_forward)
1242 errmsg_internal("skipped summarizing WAL on TLI %u from %X/%08X to %X/%08X",
1243 tli,
1246
1247 return summary_end_lsn;
1248}
1249
1250/*
1251 * Special handling for WAL records with RM_DBASE_ID.
1252 */
1253static void
1255{
1257
1258 /*
1259 * We use relfilenode zero for a given database OID and tablespace OID to
1260 * indicate that all relations with that pair of IDs have been recreated
1261 * if they exist at all. Effectively, we're setting a limit block of 0 for
1262 * all such relfilenodes.
1263 *
1264 * Technically, this special handling is only needed in the case of
1265 * XLOG_DBASE_CREATE_FILE_COPY, because that can create a whole bunch of
1266 * relation files in a directory without logging anything specific to each
1267 * one. If we didn't mark the whole DB OID/TS OID combination in some way,
1268 * then a tablespace that was dropped after the reference backup and
1269 * recreated using the FILE_COPY method prior to the incremental backup
1270 * would look just like one that was never touched at all, which would be
1271 * catastrophic.
1272 *
1273 * But it seems best to adopt this treatment for all records that drop or
1274 * create a DB OID/TS OID combination. That's similar to how we treat the
1275 * limit block for individual relations, and it's an extra layer of safety
1276 * here. We can never lose data by marking more stuff as needing to be
1277 * backed up in full.
1278 */
1279 if (info == XLOG_DBASE_CREATE_FILE_COPY)
1280 {
1282 RelFileLocator rlocator;
1283
1284 xlrec =
1286 rlocator.spcOid = xlrec->tablespace_id;
1287 rlocator.dbOid = xlrec->db_id;
1288 rlocator.relNumber = 0;
1289 BlockRefTableSetLimitBlock(brtab, &rlocator, MAIN_FORKNUM, 0);
1290 }
1291 else if (info == XLOG_DBASE_CREATE_WAL_LOG)
1292 {
1294 RelFileLocator rlocator;
1295
1297 rlocator.spcOid = xlrec->tablespace_id;
1298 rlocator.dbOid = xlrec->db_id;
1299 rlocator.relNumber = 0;
1300 BlockRefTableSetLimitBlock(brtab, &rlocator, MAIN_FORKNUM, 0);
1301 }
1302 else if (info == XLOG_DBASE_DROP)
1303 {
1305 RelFileLocator rlocator;
1306 int i;
1307
1309 rlocator.dbOid = xlrec->db_id;
1310 rlocator.relNumber = 0;
1311 for (i = 0; i < xlrec->ntablespaces; ++i)
1312 {
1313 rlocator.spcOid = xlrec->tablespace_ids[i];
1314 BlockRefTableSetLimitBlock(brtab, &rlocator, MAIN_FORKNUM, 0);
1315 }
1316 }
1317}
1318
1319/*
1320 * Special handling for WAL records with RM_SMGR_ID.
1321 */
1322static void
1324{
1326
1327 if (info == XLOG_SMGR_CREATE)
1328 {
1330
1331 /*
1332 * If a new relation fork is created on disk, there is no point
1333 * tracking anything about which blocks have been modified, because
1334 * the whole thing will be new. Hence, set the limit block for this
1335 * fork to 0.
1336 *
1337 * Ignore the FSM fork, which is not fully WAL-logged.
1338 */
1340
1341 if (xlrec->forkNum != FSM_FORKNUM)
1342 BlockRefTableSetLimitBlock(brtab, &xlrec->rlocator,
1343 xlrec->forkNum, 0);
1344 }
1345 else if (info == XLOG_SMGR_TRUNCATE)
1346 {
1348
1350
1351 /*
1352 * If a relation fork is truncated on disk, there is no point in
1353 * tracking anything about block modifications beyond the truncation
1354 * point.
1355 *
1356 * We ignore SMGR_TRUNCATE_FSM here because the FSM isn't fully
1357 * WAL-logged and thus we can't track modified blocks for it anyway.
1358 */
1359 if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0)
1360 BlockRefTableSetLimitBlock(brtab, &xlrec->rlocator,
1361 MAIN_FORKNUM, xlrec->blkno);
1362 if ((xlrec->flags & SMGR_TRUNCATE_VM) != 0)
1363 BlockRefTableSetLimitBlock(brtab, &xlrec->rlocator,
1366 }
1367}
1368
1369/*
1370 * Special handling for WAL records with RM_XACT_ID.
1371 */
1372static void
1374{
1377
1378 if (xact_info == XLOG_XACT_COMMIT ||
1380 {
1383 int i;
1384
1385 /*
1386 * Don't track modified blocks for any relations that were removed on
1387 * commit.
1388 */
1390 for (i = 0; i < parsed.nrels; ++i)
1391 {
1392 ForkNumber forknum;
1393
1394 for (forknum = 0; forknum <= MAX_FORKNUM; ++forknum)
1395 if (forknum != FSM_FORKNUM)
1396 BlockRefTableSetLimitBlock(brtab, &parsed.xlocators[i],
1397 forknum, 0);
1398 }
1399 }
1400 else if (xact_info == XLOG_XACT_ABORT ||
1402 {
1405 int i;
1406
1407 /*
1408 * Don't track modified blocks for any relations that were removed on
1409 * abort.
1410 */
1412 for (i = 0; i < parsed.nrels; ++i)
1413 {
1414 ForkNumber forknum;
1415
1416 for (forknum = 0; forknum <= MAX_FORKNUM; ++forknum)
1417 if (forknum != FSM_FORKNUM)
1418 BlockRefTableSetLimitBlock(brtab, &parsed.xlocators[i],
1419 forknum, 0);
1420 }
1421 }
1422}
1423
1424/*
1425 * Special handling for WAL records with RM_XLOG_ID.
1426 *
1427 * The return value is true if WAL summarization should stop before this
1428 * record and false otherwise. When the return value is true,
1429 * *new_fast_forward indicates whether future processing should be done
1430 * in fast forward mode (i.e. read WAL without emitting summaries) or not.
1431 */
1432static bool
1434{
1436 int record_wal_level;
1437
1438 if (info == XLOG_CHECKPOINT_REDO)
1439 {
1441
1442 /* Payload is wal_level at the time record was written. */
1444 record_wal_level = xlrec.wal_level;
1445 }
1446 else if (info == XLOG_CHECKPOINT_SHUTDOWN)
1447 {
1449
1450 /* Extract wal_level at time record was written from payload. */
1452 record_wal_level = rec_ckpt.wal_level;
1453 }
1454 else if (info == XLOG_PARAMETER_CHANGE)
1455 {
1457
1458 /* Extract wal_level at time record was written from payload. */
1460 sizeof(xl_parameter_change));
1461 record_wal_level = xlrec.wal_level;
1462 }
1463 else if (info == XLOG_END_OF_RECOVERY)
1464 {
1466
1467 /* Extract wal_level at time record was written from payload. */
1469 record_wal_level = xlrec.wal_level;
1470 }
1471 else
1472 {
1473 /* No special handling required. Return false. */
1474 return false;
1475 }
1476
1477 /*
1478 * Redo can only begin at an XLOG_CHECKPOINT_REDO or
1479 * XLOG_CHECKPOINT_SHUTDOWN record, so we want WAL summarization to begin
1480 * at those points. Hence, when those records are encountered, return
1481 * true, so that we stop just before summarizing either of those records.
1482 *
1483 * We also reach here if we just saw XLOG_END_OF_RECOVERY or
1484 * XLOG_PARAMETER_CHANGE. These are not places where recovery can start,
1485 * but they're still relevant here. A new timeline can begin with
1486 * XLOG_END_OF_RECOVERY, so we need to confirm the WAL level at that
1487 * point; and a restart can provoke XLOG_PARAMETER_CHANGE after an
1488 * intervening change to postgresql.conf, which might force us to stop
1489 * summarizing.
1490 */
1492 return true;
1493}
1494
1495/*
1496 * Similar to read_local_xlog_page, but limited to read from one particular
1497 * timeline. If the end of WAL is reached, it will wait for more if reading
1498 * from the current timeline, or give up if reading from a historic timeline.
1499 * In the latter case, it will also set private_data->end_of_wal = true.
1500 *
1501 * Caller must set private_data->tli to the TLI of interest,
1502 * private_data->read_upto to the lowest LSN that is not known to be safe
1503 * to read on that timeline, and private_data->historic to true if and only
1504 * if the timeline is not the current timeline. This function will update
1505 * private_data->read_upto and private_data->historic if more WAL appears
1506 * on the current timeline or if the current timeline becomes historic.
1507 */
1508static int
1512{
1513 int count;
1515 SummarizerReadLocalXLogPrivate *private_data;
1516
1518
1519 private_data = (SummarizerReadLocalXLogPrivate *)
1520 state->private_data;
1521
1522 while (1)
1523 {
1525 {
1526 /*
1527 * more than one block available; read only that block, have
1528 * caller come back if they need more.
1529 */
1530 count = XLOG_BLCKSZ;
1531 break;
1532 }
1533 else if (targetPagePtr + reqLen > private_data->read_upto)
1534 {
1535 /* We don't seem to have enough data. */
1536 if (private_data->historic)
1537 {
1538 /*
1539 * This is a historic timeline, so there will never be any
1540 * more data than we have currently.
1541 */
1542 private_data->end_of_wal = true;
1543 return -1;
1544 }
1545 else
1546 {
1549
1550 /*
1551 * This is - or at least was up until very recently - the
1552 * current timeline, so more data might show up. Delay here
1553 * so we don't tight-loop.
1554 */
1557
1558 /* Recheck end-of-WAL. */
1560 if (private_data->tli == latest_tli)
1561 {
1562 /* Still the current timeline, update max LSN. */
1563 Assert(latest_lsn >= private_data->read_upto);
1564 private_data->read_upto = latest_lsn;
1565 }
1566 else
1567 {
1570
1571 /*
1572 * The timeline we're scanning is no longer the latest
1573 * one. Figure out when it ended.
1574 */
1575 private_data->historic = true;
1576 switchpoint = tliSwitchPoint(private_data->tli, tles,
1577 NULL);
1578
1579 /*
1580 * Allow reads up to exactly the switch point.
1581 *
1582 * It's possible that this will cause read_upto to move
1583 * backwards, because we might have been promoted before
1584 * reaching the end of the previous timeline. In that
1585 * case, the next loop iteration will likely conclude that
1586 * we've reached end of WAL.
1587 */
1588 private_data->read_upto = switchpoint;
1589
1590 /* Debugging output. */
1592 errmsg_internal("timeline %u became historic, can read up to %X/%08X",
1593 private_data->tli, LSN_FORMAT_ARGS(private_data->read_upto)));
1594 }
1595
1596 /* Go around and try again. */
1597 }
1598 }
1599 else
1600 {
1601 /* enough bytes available to satisfy the request */
1602 count = private_data->read_upto - targetPagePtr;
1603 break;
1604 }
1605 }
1606
1607 if (!WALRead(state, cur_page, targetPagePtr, count,
1608 private_data->tli, &errinfo))
1610
1611 /* Track that we read a page, for sleep time calculation. */
1613
1614 /* number of valid bytes in the buffer */
1615 return count;
1616}
1617
1618/*
1619 * Sleep for long enough that we believe it's likely that more WAL will
1620 * be available afterwards.
1621 */
1622static void
1624{
1626 {
1627 /*
1628 * No pages were read since the last sleep, so double the sleep time,
1629 * but not beyond the maximum allowable value.
1630 */
1632 }
1633 else if (pages_read_since_last_sleep > 1)
1634 {
1635 /*
1636 * Multiple pages were read since the last sleep, so reduce the sleep
1637 * time.
1638 *
1639 * A large burst of activity should be able to quickly reduce the
1640 * sleep time to the minimum, but we don't want a handful of extra WAL
1641 * records to provoke a strong reaction. We choose to reduce the sleep
1642 * time by 1 quantum for each page read beyond the first, which is a
1643 * fairly arbitrary way of trying to be reactive without overreacting.
1644 */
1646 sleep_quanta = 1;
1647 else
1649 }
1650
1651 /* Report pending statistics to the cumulative stats system. */
1652 pgstat_report_wal(false);
1653
1654 /* OK, now sleep. */
1660
1661 /* Reset count of pages read. */
1663}
1664
1665/*
1666 * Remove WAL summaries whose mtimes are older than wal_summary_keep_time.
1667 */
1668static void
1670{
1672 List *wslist;
1674
1675 /* If WAL summary removal is disabled, don't do anything. */
1676 if (wal_summary_keep_time == 0)
1677 return;
1678
1679 /*
1680 * If the redo pointer has not advanced, don't do anything.
1681 *
1682 * This has the effect that we only try to remove old WAL summary files
1683 * once per checkpoint cycle.
1684 */
1686 return;
1688
1689 /*
1690 * Files should only be removed if the last modification time precedes the
1691 * cutoff time we compute here.
1692 */
1694
1695 /* Get all the summaries that currently exist. */
1697
1698 /* Loop until all summaries have been considered for removal. */
1699 while (wslist != NIL)
1700 {
1701 ListCell *lc;
1705
1707
1708 /*
1709 * Pick a timeline for which some summary files still exist on disk,
1710 * and find the oldest LSN that still exists on disk for that
1711 * timeline.
1712 */
1715 if (oldest_segno != 0)
1717 oldest_lsn);
1718
1719
1720 /* Consider each WAL file on the selected timeline in turn. */
1721 foreach(lc, wslist)
1722 {
1724
1726
1727 /* If it's not on this timeline, it's not time to consider it. */
1728 if (selected_tli != ws->tli)
1729 continue;
1730
1731 /*
1732 * If the WAL doesn't exist any more, we can remove it if the file
1733 * modification time is old enough.
1734 */
1735 if (!XLogRecPtrIsValid(oldest_lsn) || ws->end_lsn <= oldest_lsn)
1737
1738 /*
1739 * Whether we removed the file or not, we need not consider it
1740 * again.
1741 */
1743 pfree(ws);
1744 }
1745 }
1746}
void pgaio_error_cleanup(void)
Definition aio.c:1175
void AuxiliaryProcessMainCommon(void)
Definition auxprocess.c:41
List * readTimeLineHistory(TimeLineID targetTLI)
Definition timeline.c:77
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition timeline.c:573
sigset_t UnBlockSig
Definition pqsignal.c:22
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.c:1765
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1649
void BlockRefTableMarkBlockModified(BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum)
void BlockRefTableSetLimitBlock(BlockRefTable *brtab, const RelFileLocator *rlocator, ForkNumber forknum, BlockNumber limit_block)
void WriteBlockRefTable(BlockRefTable *brtab, io_callback_fn write_callback, void *write_callback_arg)
void(*) BlockRefTable CreateEmptyBlockRefTable)(void)
uint32 BlockNumber
Definition block.h:31
#define Min(x, y)
Definition c.h:1131
uint8_t uint8
Definition c.h:681
#define Assert(condition)
Definition c.h:1002
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
int64 TimestampTz
Definition timestamp.h:39
#define MINS_PER_HOUR
Definition timestamp.h:129
#define SECS_PER_MINUTE
Definition timestamp.h:128
#define HOURS_PER_DAY
Definition timestamp.h:118
#define XLOG_DBASE_CREATE_WAL_LOG
#define XLOG_DBASE_DROP
#define XLOG_DBASE_CREATE_FILE_COPY
void AtEOXact_HashTables(bool isCommit)
Definition dynahash.c:1864
Datum arg
Definition elog.c:1323
void EmitErrorReport(void)
Definition elog.c:1883
int errcode_for_file_access(void)
Definition elog.c:898
ErrorContextCallback * error_context_stack
Definition elog.c:100
void FlushErrorState(void)
Definition elog.c:2063
int errcode(int sqlerrcode)
Definition elog.c:875
sigjmp_buf * PG_exception_stack
Definition elog.c:102
int errdetail(const char *fmt,...) pg_attribute_printf(1
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
int int int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...) pg_attribute_printf(1
#define DEBUG1
Definition elog.h:31
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition fd.c:783
void AtEOXact_Files(bool isCommit)
Definition fd.c:3212
void FileClose(File file)
Definition fd.c:1966
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition fd.c:1563
#define palloc0_object(type)
Definition fe_memutils.h:90
volatile sig_atomic_t LogMemoryContextPending
Definition globals.c:41
volatile sig_atomic_t ProcSignalBarrierPending
Definition globals.c:40
ProcNumber MyProcNumber
Definition globals.c:92
struct Latch * MyLatch
Definition globals.c:65
void ProcessConfigFile(GucContext context)
Definition guc-file.l:120
@ PGC_SIGHUP
Definition guc.h:75
void SignalHandlerForShutdownRequest(SIGNAL_ARGS)
Definition interrupt.c:104
volatile sig_atomic_t ShutdownRequestPending
Definition interrupt.c:28
volatile sig_atomic_t ConfigReloadPending
Definition interrupt.c:27
void SignalHandlerForConfigReload(SIGNAL_ARGS)
Definition interrupt.c:61
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
void proc_exit(int code)
Definition ipc.c:105
int i
Definition isn.c:77
void SetLatch(Latch *latch)
Definition latch.c:290
void ResetLatch(Latch *latch)
Definition latch.c:374
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition latch.c:172
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
void LWLockReleaseAll(void)
Definition lwlock.c:1866
@ LW_SHARED
Definition lwlock.h:105
@ LW_EXCLUSIVE
Definition lwlock.h:104
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:406
void pfree(void *pointer)
Definition mcxt.c:1619
MemoryContext TopMemoryContext
Definition mcxt.c:167
void ProcessLogMemoryContextInterrupt(void)
Definition mcxt.c:1343
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define RESUME_INTERRUPTS()
Definition miscadmin.h:138
#define AmWalSummarizerProcess()
Definition miscadmin.h:398
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#define HOLD_INTERRUPTS()
Definition miscadmin.h:136
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
#define MAXPGPATH
#define XLOG_CHECKPOINT_REDO
Definition pg_control.h:86
#define XLOG_CHECKPOINT_SHUTDOWN
Definition pg_control.h:72
#define XLOG_PARAMETER_CHANGE
Definition pg_control.h:78
#define XLOG_END_OF_RECOVERY
Definition pg_control.h:81
#define lfirst(lc)
Definition pg_list.h:172
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define foreach_delete_current(lst, var_or_cell)
Definition pg_list.h:423
static void * list_nth(const List *list, int n)
Definition pg_list.h:331
#define linitial(l)
Definition pg_list.h:178
void pgstat_report_wal(bool force)
Definition pgstat_wal.c:46
#define pqsignal
Definition port.h:548
#define PG_SIG_IGN
Definition port.h:552
#define snprintf
Definition port.h:261
#define PG_SIG_DFL
Definition port.h:551
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
#define GetPGProcByNumber(n)
Definition proc.h:506
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
int ProcNumber
Definition procnumber.h:24
void ProcessProcSignalBarrier(void)
Definition procsignal.c:511
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition procsignal.c:696
ForkNumber
Definition relpath.h:56
@ FSM_FORKNUM
Definition relpath.h:59
@ VISIBILITYMAP_FORKNUM
Definition relpath.h:60
@ MAIN_FORKNUM
Definition relpath.h:58
#define MAX_FORKNUM
Definition relpath.h:70
void ReleaseAuxProcessResources(bool isCommit)
Definition resowner.c:1026
#define ShmemRequestStruct(...)
Definition shmem.h:176
#define SMGR_TRUNCATE_VM
#define XLOG_SMGR_CREATE
#define XLOG_SMGR_TRUNCATE
#define SMGR_TRUNCATE_HEAP
Definition pg_list.h:54
RelFileNumber relNumber
ShmemRequestCallback request_fn
Definition shmem.h:133
XLogRecPtr summarized_lsn
TimeLineID summarized_tli
ConditionVariable summary_file_cv
ProcNumber summarizer_pgprocno
XLogRecPtr pending_lsn
off_t filepos
Definition walsummary.h:24
XLogRecPtr EndRecPtr
Definition xlogreader.h:206
XLogRecPtr ReadRecPtr
Definition xlogreader.h:205
void * private_data
Definition xlogreader.h:195
#define TimestampTzPlusMilliseconds(tz, ms)
Definition timestamp.h:85
BlockNumber visibilitymap_truncation_length(BlockNumber nheapblocks)
static void pgstat_report_wait_end(void)
Definition wait_event.h:83
const char * name
#define WL_TIMEOUT
#define WL_EXIT_ON_PM_DEATH
#define WL_LATCH_SET
XLogRecPtr GetWalRcvFlushRecPtr(XLogRecPtr *latestChunkStart, TimeLineID *receiveTLI)
static XLogRecPtr redo_pointer_at_last_summary_removal
#define MAX_SLEEP_QUANTA
static long pages_read_since_last_sleep
static XLogRecPtr GetLatestLSN(TimeLineID *tli)
void WalSummarizerMain(const void *startup_data, size_t startup_data_len)
static bool SummarizeXlogRecord(XLogReaderState *xlogreader, bool *new_fast_forward)
const ShmemCallbacks WalSummarizerShmemCallbacks
static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact, XLogRecPtr switch_lsn, XLogRecPtr maximum_lsn)
static WalSummarizerData * WalSummarizerCtl
static void ProcessWalSummarizerInterrupts(void)
static void SummarizeXactRecord(XLogReaderState *xlogreader, BlockRefTable *brtab)
static void WalSummarizerShmemInit(void *arg)
bool summarize_wal
void WaitForWalSummarization(XLogRecPtr lsn)
static void SummarizeDbaseRecord(XLogReaderState *xlogreader, BlockRefTable *brtab)
#define MS_PER_SLEEP_QUANTUM
void GetWalSummarizerState(TimeLineID *summarized_tli, XLogRecPtr *summarized_lsn, XLogRecPtr *pending_lsn, int *summarizer_pid)
static long sleep_quanta
int wal_summary_keep_time
static void WalSummarizerShmemRequest(void *arg)
static int summarizer_read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
static void WalSummarizerShutdown(int code, Datum arg)
static void SummarizeSmgrRecord(XLogReaderState *xlogreader, BlockRefTable *brtab)
static void MaybeRemoveOldWalSummaries(void)
void WakeupWalSummarizer(void)
XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact)
static void summarizer_wait_for_wal(void)
void RemoveWalSummaryIfOlderThan(WalSummaryFile *ws, time_t cutoff_time)
Definition walsummary.c:230
size_t WriteWalSummary(void *wal_summary_io, void *data, size_t length)
Definition walsummary.c:294
List * GetWalSummaries(TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
Definition walsummary.c:43
#define SIGCHLD
Definition win32_port.h:168
#define SIGHUP
Definition win32_port.h:158
#define SIGPIPE
Definition win32_port.h:163
#define SIGUSR1
Definition win32_port.h:170
#define SIGALRM
Definition win32_port.h:164
#define SIGUSR2
Definition win32_port.h:171
#define XLOG_XACT_COMMIT_PREPARED
Definition xact.h:173
#define XLOG_XACT_COMMIT
Definition xact.h:170
#define XLOG_XACT_OPMASK
Definition xact.h:180
#define XLOG_XACT_ABORT
Definition xact.h:172
#define XLOG_XACT_ABORT_PREPARED
Definition xact.h:174
void ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
Definition xactdesc.c:35
void ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
Definition xactdesc.c:141
bool RecoveryInProgress(void)
Definition xlog.c:6835
XLogRecPtr GetRedoRecPtr(void)
Definition xlog.c:6938
int wal_segment_size
Definition xlog.c:150
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition xlog.c:7000
XLogSegNo XLogGetOldestSegno(TimeLineID tli)
Definition xlog.c:3824
TimeLineID GetWALInsertionTimeLineIfSet(void)
Definition xlog.c:7037
@ WAL_LEVEL_MINIMAL
Definition xlog.h:76
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
#define XLOGDIR
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
uint64 XLogRecPtr
Definition xlogdefs.h:21
#define InvalidXLogRecPtr
Definition xlogdefs.h:28
uint32 TimeLineID
Definition xlogdefs.h:63
uint64 XLogSegNo
Definition xlogdefs.h:52
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition xlogreader.c:108
bool WALRead(XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition xlogreader.c:391
void XLogReaderFree(XLogReaderState *state)
Definition xlogreader.c:163
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)
Definition xlogreader.c:233
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition xlogreader.h:411
#define XLogRecGetData(decoder)
Definition xlogreader.h:415
#define XL_ROUTINE(...)
Definition xlogreader.h:117
#define XLogRecMaxBlockId(decoder)
Definition xlogreader.h:418
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
static XLogReaderState * xlogreader
void wal_segment_close(XLogReaderState *state)
Definition xlogutils.c:855
void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
Definition xlogutils.c:830
void WALReadRaiseError(WALReadError *errinfo)
Definition xlogutils.c:1047