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"
26#include "access/xlog.h"
28#include "access/xlogrecovery.h"
29#include "access/xlogutils.h"
30#include "backup/walsummary.h"
33#include "common/blkreftable.h"
34#include "libpq/pqsignal.h"
35#include "miscadmin.h"
36#include "pgstat.h"
41#include "storage/aio_subsys.h"
42#include "storage/fd.h"
43#include "storage/ipc.h"
44#include "storage/latch.h"
45#include "storage/lwlock.h"
46#include "storage/proc.h"
47#include "storage/procsignal.h"
48#include "storage/shmem.h"
49#include "utils/guc.h"
50#include "utils/memutils.h"
51#include "utils/wait_event.h"
52
53/*
54 * Data in shared memory related to WAL summarization.
55 */
56typedef struct
57{
58 /*
59 * These fields are protected by WALSummarizerLock.
60 *
61 * Until we've discovered what summary files already exist on disk and
62 * stored that information in shared memory, initialized is false and the
63 * other fields here contain no meaningful information. After that has
64 * been done, initialized is true.
65 *
66 * summarized_tli and summarized_lsn indicate the last LSN and TLI at
67 * which the next summary file will start. Normally, these are the LSN and
68 * TLI at which the last file ended; in such case, lsn_is_exact is true.
69 * If, however, the LSN is just an approximation, then lsn_is_exact is
70 * false. This can happen if, for example, there are no existing WAL
71 * summary files at startup. In that case, we have to derive the position
72 * at which to start summarizing from the WAL files that exist on disk,
73 * and so the LSN might point to the start of the next file even though
74 * that might happen to be in the middle of a WAL record.
75 *
76 * summarizer_pgprocno is the proc number of the summarizer process, if
77 * one is running, or else INVALID_PROC_NUMBER.
78 *
79 * pending_lsn is used by the summarizer to advertise the ending LSN of a
80 * record it has recently read. It shouldn't ever be less than
81 * summarized_lsn, but might be greater, because the summarizer buffers
82 * data for a range of LSNs in memory before writing out a new file.
83 */
90
91 /*
92 * This field handles its own synchronization.
93 */
96
97/*
98 * Private data for our xlogreader's page read callback.
99 */
107
108/* Pointer to shared memory state. */
110
111/*
112 * When we reach end of WAL and need to read more, we sleep for a number of
113 * milliseconds that is an integer multiple of MS_PER_SLEEP_QUANTUM. This is
114 * the multiplier. It should vary between 1 and MAX_SLEEP_QUANTA, depending
115 * on system activity. See summarizer_wait_for_wal() for how we adjust this.
116 */
117static long sleep_quanta = 1;
118
119/*
120 * The sleep time will always be a multiple of 200ms and will not exceed
121 * thirty seconds (150 * 200 = 30 * 1000). Note that the timeout here needs
122 * to be substantially less than the maximum amount of time for which an
123 * incremental backup will wait for this process to catch up. Otherwise, an
124 * incremental backup might time out on an idle system just because we sleep
125 * for too long.
126 */
127#define MAX_SLEEP_QUANTA 150
128#define MS_PER_SLEEP_QUANTUM 200
129
130/*
131 * This is a count of the number of pages of WAL that we've read since the
132 * last time we waited for more WAL to appear.
133 */
135
136/*
137 * Most recent RedoRecPtr value observed by MaybeRemoveOldWalSummaries.
138 */
140
141/*
142 * GUC parameters
143 */
144bool summarize_wal = false;
146
147static void WalSummarizerShutdown(int code, Datum arg);
149static void ProcessWalSummarizerInterrupts(void);
150static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn,
154 BlockRefTable *brtab);
156 BlockRefTable *brtab);
158 BlockRefTable *brtab);
160 bool *new_fast_forward);
163 int reqLen,
165 char *cur_page);
166static void summarizer_wait_for_wal(void);
167static void MaybeRemoveOldWalSummaries(void);
168
169/*
170 * Amount of shared memory required for this module.
171 */
172Size
174{
175 return sizeof(WalSummarizerData);
176}
177
178/*
179 * Create or attach to shared memory segment for this module.
180 */
181void
183{
184 bool found;
185
187 ShmemInitStruct("Wal Summarizer Ctl", WalSummarizerShmemSize(),
188 &found);
189
190 if (!found)
191 {
192 /*
193 * First time through, so initialize.
194 *
195 * We're just filling in dummy values here -- the real initialization
196 * will happen when GetOldestUnsummarizedLSN() is called for the first
197 * time.
198 */
206 }
207}
208
209/*
210 * Entry point for walsummarizer process.
211 */
212void
214{
216 MemoryContext context;
217
218 /*
219 * Within this function, 'current_lsn' and 'current_tli' refer to the
220 * point from which the next WAL summary file should start. 'exact' is
221 * true if 'current_lsn' is known to be the start of a WAL record or WAL
222 * segment, and false if it might be in the middle of a record someplace.
223 *
224 * 'switch_lsn' and 'switch_tli', if set, are the LSN at which we need to
225 * switch to a new timeline and the timeline to which we need to switch.
226 * If not set, we either haven't figured out the answers yet or we're
227 * already on the latest timeline.
228 */
231 bool exact;
234
236
238
240 (errmsg_internal("WAL summarizer started")));
241
242 /*
243 * Properly accept or ignore signals the postmaster might send us
244 *
245 * We have no particular use for SIGINT at the moment, but seems
246 * reasonable to treat like SIGTERM.
247 */
251 /* SIGQUIT handler was already set up by InitPostmasterChild */
255 pqsignal(SIGUSR2, SIG_IGN); /* not used */
256
257 /* Advertise ourselves. */
262
263 /* Create and switch to a memory context that we can reset on error. */
265 "Wal Summarizer",
267 MemoryContextSwitchTo(context);
268
269 /*
270 * Reset some signals that are accepted by postmaster but not here
271 */
273
274 /*
275 * If an exception is encountered, processing resumes here.
276 */
277 if (sigsetjmp(local_sigjmp_buf, 1) != 0)
278 {
279 /* Since not using PG_TRY, must reset error stack by hand */
281
282 /* Prevent interrupts while cleaning up */
284
285 /* Report the error to the server log */
287
288 /* Release resources we might have acquired. */
294 AtEOXact_Files(false);
295 AtEOXact_HashTables(false);
296
297 /*
298 * Now return to normal top-level context and clear ErrorContext for
299 * next time.
300 */
301 MemoryContextSwitchTo(context);
303
304 /* Flush any leaked data in the top-level context */
305 MemoryContextReset(context);
306
307 /* Now we can allow interrupts again */
309
310 /*
311 * Sleep for 10 seconds before attempting to resume operations in
312 * order to avoid excessive logging.
313 *
314 * Many of the likely error conditions are things that will repeat
315 * every time. For example, if the WAL can't be read or the summary
316 * can't be written, only administrator action will cure the problem.
317 * So a really fast retry time doesn't seem to be especially
318 * beneficial, and it will clutter the logs.
319 */
322 10000,
324 }
325
326 /* We can now handle ereport(ERROR) */
328
329 /*
330 * Unblock signals (they were blocked when the postmaster forked us)
331 */
333
334 /*
335 * Fetch information about previous progress from shared memory, and ask
336 * GetOldestUnsummarizedLSN to reset pending_lsn to summarized_lsn. We
337 * might be recovering from an error, and if so, pending_lsn might have
338 * advanced past summarized_lsn, but any WAL we read previously has been
339 * lost and will need to be reread.
340 *
341 * If we discover that WAL summarization is not enabled, just exit.
342 */
345 proc_exit(0);
346
347 /*
348 * Loop forever
349 */
350 for (;;)
351 {
355
356 /* Flush any leaked data in the top-level context */
357 MemoryContextReset(context);
358
359 /* Process any signals received recently. */
361
362 /* If it's time to remove any old WAL summaries, do that now. */
364
365 /* Find the LSN and TLI up to which we can safely summarize. */
367
368 /*
369 * If we're summarizing a historic timeline and we haven't yet
370 * computed the point at which to switch to the next timeline, do that
371 * now.
372 *
373 * Note that if this is a standby, what was previously the current
374 * timeline could become historic at any time.
375 *
376 * We could try to make this more efficient by caching the results of
377 * readTimeLineHistory when latest_tli has not changed, but since we
378 * only have to do this once per timeline switch, we probably wouldn't
379 * save any significant amount of work in practice.
380 */
382 {
384
387 errmsg_internal("switch point from TLI %u to TLI %u is at %X/%08X",
389 }
390
391 /*
392 * If we've reached the switch LSN, we can't summarize anything else
393 * on this timeline. Switch to the next timeline and go around again,
394 * backing up to the exact switch point if we passed it.
395 */
397 {
398 /* Restart summarization from switch point. */
401
402 /* Next timeline and switch point, if any, not yet known. */
404 switch_tli = 0;
405
406 /* Update (really, rewind, if needed) state in shared memory. */
413
414 continue;
415 }
416
417 /* 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
921 /* Initialize private data for xlogreader. */
923 private_data->tli = tli;
924 private_data->historic = XLogRecPtrIsValid(switch_lsn);
925 private_data->read_upto = maximum_lsn;
926
927 /* Create xlogreader. */
930 .segment_open = &wal_segment_open,
931 .segment_close = &wal_segment_close),
932 private_data);
933 if (xlogreader == NULL)
936 errmsg("out of memory"),
937 errdetail("Failed while allocating a WAL reading processor.")));
938
939 /*
940 * When exact = false, we're starting from an arbitrary point in the WAL
941 * and must search forward for the start of the next record.
942 *
943 * When exact = true, start_lsn should be either the LSN where a record
944 * begins, or the LSN of a page where the page header is immediately
945 * followed by the start of a new record. XLogBeginRead should tolerate
946 * either case.
947 *
948 * We need to allow for both cases because the behavior of xlogreader
949 * varies. When a record spans two or more xlog pages, the ending LSN
950 * reported by xlogreader will be the starting LSN of the following
951 * record, but when an xlog page boundary falls between two records, the
952 * end LSN for the first will be reported as the first byte of the
953 * following page. We can't know until we read that page how large the
954 * header will be, but we'll have to skip over it to find the next record.
955 */
956 if (exact)
957 {
958 /*
959 * Even if start_lsn is the beginning of a page rather than the
960 * beginning of the first record on that page, we should still use it
961 * as the start LSN for the summary file. That's because we detect
962 * missing summary files by looking for cases where the end LSN of one
963 * file is less than the start LSN of the next file. When only a page
964 * header is skipped, nothing has been missed.
965 */
966 XLogBeginRead(xlogreader, start_lsn);
967 summary_start_lsn = start_lsn;
968 }
969 else
970 {
973 {
974 /*
975 * If we hit end-of-WAL while trying to find the next valid
976 * record, we must be on a historic timeline that has no valid
977 * records that begin after start_lsn and before end of WAL.
978 */
979 if (private_data->end_of_wal)
980 {
982 errmsg_internal("could not read WAL from timeline %u at %X/%08X: end of WAL at %X/%08X",
983 tli,
984 LSN_FORMAT_ARGS(start_lsn),
985 LSN_FORMAT_ARGS(private_data->read_upto)));
986
987 /*
988 * The timeline ends at or after start_lsn, without containing
989 * any records. Thus, we must make sure the main loop does not
990 * iterate. If start_lsn is the end of the timeline, then we
991 * won't actually emit an empty summary file, but otherwise,
992 * we must, to capture the fact that the LSN range in question
993 * contains no interesting WAL records.
994 */
995 summary_start_lsn = start_lsn;
996 summary_end_lsn = private_data->read_upto;
998 }
999 else
1000 ereport(ERROR,
1001 errmsg("could not find a valid record after %X/%08X",
1002 LSN_FORMAT_ARGS(start_lsn)));
1003 }
1004
1005 /* We shouldn't go backward. */
1006 Assert(summary_start_lsn >= start_lsn);
1007 }
1008
1009 /*
1010 * Main loop: read xlog records one by one.
1011 */
1012 while (1)
1013 {
1014 int block_id;
1015 char *errormsg;
1016 XLogRecord *record;
1017 uint8 rmid;
1018
1020
1021 /* We shouldn't go backward. */
1023
1024 /* Now read the next record. */
1025 record = XLogReadRecord(xlogreader, &errormsg);
1026 if (record == NULL)
1027 {
1028 if (private_data->end_of_wal)
1029 {
1030 /*
1031 * This timeline must be historic and must end before we were
1032 * able to read a complete record.
1033 */
1035 errmsg_internal("could not read WAL from timeline %u at %X/%08X: end of WAL at %X/%08X",
1036 tli,
1038 LSN_FORMAT_ARGS(private_data->read_upto)));
1039 /* Summary ends at end of WAL. */
1040 summary_end_lsn = private_data->read_upto;
1041 break;
1042 }
1043 if (errormsg)
1044 ereport(ERROR,
1046 errmsg("could not read WAL from timeline %u at %X/%08X: %s",
1048 errormsg)));
1049 else
1050 ereport(ERROR,
1052 errmsg("could not read WAL from timeline %u at %X/%08X",
1054 }
1055
1056 /* We shouldn't go backward. */
1058
1061 {
1062 /*
1063 * Whoops! We've read a record that *starts* after the switch LSN,
1064 * contrary to our goal of reading only until we hit the first
1065 * record that ends at or after the switch LSN. Pretend we didn't
1066 * read it after all by bailing out of this loop right here,
1067 * before we do anything with this record.
1068 *
1069 * This can happen because the last record before the switch LSN
1070 * might be continued across multiple pages, and then we might
1071 * come to a page with XLP_FIRST_IS_OVERWRITE_CONTRECORD set. In
1072 * that case, the record that was continued across multiple pages
1073 * is incomplete and will be disregarded, and the read will
1074 * restart from the beginning of the page that is flagged
1075 * XLP_FIRST_IS_OVERWRITE_CONTRECORD.
1076 *
1077 * If this case occurs, we can fairly say that the current summary
1078 * file ends at the switch LSN exactly. The first record on the
1079 * page marked XLP_FIRST_IS_OVERWRITE_CONTRECORD will be
1080 * discovered when generating the next summary file.
1081 */
1083 break;
1084 }
1085
1086 /*
1087 * Certain types of records require special handling. Redo points and
1088 * shutdown checkpoints trigger creation of new summary files and can
1089 * also cause us to enter or exit "fast forward" mode. Other types of
1090 * records can require special updates to the block reference table.
1091 */
1092 rmid = XLogRecGetRmid(xlogreader);
1093 if (rmid == RM_XLOG_ID)
1094 {
1095 bool new_fast_forward;
1096
1097 /*
1098 * If we've already processed some WAL records when we hit a redo
1099 * point or shutdown checkpoint, then we stop summarization before
1100 * including this record in the current file, so that it will be
1101 * the first record in the next file.
1102 *
1103 * When we hit one of those record types as the first record in a
1104 * file, we adjust our notion of whether we're fast-forwarding.
1105 * Any WAL generated with wal_level=minimal must be skipped
1106 * without actually generating any summary file, because an
1107 * incremental backup that crosses such WAL would be unsafe.
1108 */
1110 {
1112 {
1114 break;
1115 }
1116 else
1117 fast_forward = new_fast_forward;
1118 }
1119 }
1120 else if (!fast_forward)
1121 {
1122 /*
1123 * This switch handles record types that require extra updates to
1124 * the contents of the block reference table.
1125 */
1126 switch (rmid)
1127 {
1128 case RM_DBASE_ID:
1130 break;
1131 case RM_SMGR_ID:
1133 break;
1134 case RM_XACT_ID:
1136 break;
1137 }
1138 }
1139
1140 /*
1141 * If we're in fast-forward mode, we don't really need to do anything.
1142 * Otherwise, feed block references from xlog record to block
1143 * reference table.
1144 */
1145 if (!fast_forward)
1146 {
1148 block_id++)
1149 {
1150 RelFileLocator rlocator;
1151 ForkNumber forknum;
1152 BlockNumber blocknum;
1153
1155 &forknum, &blocknum, NULL))
1156 continue;
1157
1158 /*
1159 * As we do elsewhere, ignore the FSM fork, because it's not
1160 * fully WAL-logged.
1161 */
1162 if (forknum != FSM_FORKNUM)
1163 BlockRefTableMarkBlockModified(brtab, &rlocator, forknum,
1164 blocknum);
1165 }
1166 }
1167
1168 /* Update our notion of where this summary file ends. */
1170
1171 /* Also update shared memory. */
1176
1177 /*
1178 * If we have a switch LSN and have reached it, stop before reading
1179 * the next record.
1180 */
1183 break;
1184 }
1185
1186 /* Destroy xlogreader. */
1189
1190 /*
1191 * If a timeline switch occurs, we may fail to make any progress at all
1192 * before exiting the loop above. If that happens, we don't write a WAL
1193 * summary file at all. We can also skip writing a file if we're in
1194 * fast-forward mode.
1195 */
1196 if (summary_end_lsn > summary_start_lsn && !fast_forward)
1197 {
1198 /* Generate temporary and final path name. */
1200 XLOGDIR "/summaries/temp.summary");
1202 XLOGDIR "/summaries/%08X%08X%08X%08X%08X.summary",
1203 tli,
1206
1207 /* Open the temporary file for writing. */
1208 io.filepos = 0;
1210 if (io.file < 0)
1211 ereport(ERROR,
1213 errmsg("could not create file \"%s\": %m", temp_path)));
1214
1215 /* Write the data. */
1217
1218 /* Close temporary file and shut down xlogreader. */
1219 FileClose(io.file);
1220
1221 /* Tell the user what we did. */
1223 errmsg_internal("summarized WAL on TLI %u from %X/%08X to %X/%08X",
1224 tli,
1227
1228 /* Durably rename the new summary into place. */
1230 }
1231
1232 /* If we skipped a non-zero amount of WAL, log a debug message. */
1233 if (summary_end_lsn > summary_start_lsn && fast_forward)
1235 errmsg_internal("skipped summarizing WAL on TLI %u from %X/%08X to %X/%08X",
1236 tli,
1239
1240 return summary_end_lsn;
1241}
1242
1243/*
1244 * Special handling for WAL records with RM_DBASE_ID.
1245 */
1246static void
1248{
1250
1251 /*
1252 * We use relfilenode zero for a given database OID and tablespace OID to
1253 * indicate that all relations with that pair of IDs have been recreated
1254 * if they exist at all. Effectively, we're setting a limit block of 0 for
1255 * all such relfilenodes.
1256 *
1257 * Technically, this special handling is only needed in the case of
1258 * XLOG_DBASE_CREATE_FILE_COPY, because that can create a whole bunch of
1259 * relation files in a directory without logging anything specific to each
1260 * one. If we didn't mark the whole DB OID/TS OID combination in some way,
1261 * then a tablespace that was dropped after the reference backup and
1262 * recreated using the FILE_COPY method prior to the incremental backup
1263 * would look just like one that was never touched at all, which would be
1264 * catastrophic.
1265 *
1266 * But it seems best to adopt this treatment for all records that drop or
1267 * create a DB OID/TS OID combination. That's similar to how we treat the
1268 * limit block for individual relations, and it's an extra layer of safety
1269 * here. We can never lose data by marking more stuff as needing to be
1270 * backed up in full.
1271 */
1272 if (info == XLOG_DBASE_CREATE_FILE_COPY)
1273 {
1275 RelFileLocator rlocator;
1276
1277 xlrec =
1279 rlocator.spcOid = xlrec->tablespace_id;
1280 rlocator.dbOid = xlrec->db_id;
1281 rlocator.relNumber = 0;
1282 BlockRefTableSetLimitBlock(brtab, &rlocator, MAIN_FORKNUM, 0);
1283 }
1284 else if (info == XLOG_DBASE_CREATE_WAL_LOG)
1285 {
1287 RelFileLocator rlocator;
1288
1290 rlocator.spcOid = xlrec->tablespace_id;
1291 rlocator.dbOid = xlrec->db_id;
1292 rlocator.relNumber = 0;
1293 BlockRefTableSetLimitBlock(brtab, &rlocator, MAIN_FORKNUM, 0);
1294 }
1295 else if (info == XLOG_DBASE_DROP)
1296 {
1298 RelFileLocator rlocator;
1299 int i;
1300
1302 rlocator.dbOid = xlrec->db_id;
1303 rlocator.relNumber = 0;
1304 for (i = 0; i < xlrec->ntablespaces; ++i)
1305 {
1306 rlocator.spcOid = xlrec->tablespace_ids[i];
1307 BlockRefTableSetLimitBlock(brtab, &rlocator, MAIN_FORKNUM, 0);
1308 }
1309 }
1310}
1311
1312/*
1313 * Special handling for WAL records with RM_SMGR_ID.
1314 */
1315static void
1317{
1319
1320 if (info == XLOG_SMGR_CREATE)
1321 {
1323
1324 /*
1325 * If a new relation fork is created on disk, there is no point
1326 * tracking anything about which blocks have been modified, because
1327 * the whole thing will be new. Hence, set the limit block for this
1328 * fork to 0.
1329 *
1330 * Ignore the FSM fork, which is not fully WAL-logged.
1331 */
1333
1334 if (xlrec->forkNum != FSM_FORKNUM)
1335 BlockRefTableSetLimitBlock(brtab, &xlrec->rlocator,
1336 xlrec->forkNum, 0);
1337 }
1338 else if (info == XLOG_SMGR_TRUNCATE)
1339 {
1341
1343
1344 /*
1345 * If a relation fork is truncated on disk, there is no point in
1346 * tracking anything about block modifications beyond the truncation
1347 * point.
1348 *
1349 * We ignore SMGR_TRUNCATE_FSM here because the FSM isn't fully
1350 * WAL-logged and thus we can't track modified blocks for it anyway.
1351 */
1352 if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0)
1353 BlockRefTableSetLimitBlock(brtab, &xlrec->rlocator,
1354 MAIN_FORKNUM, xlrec->blkno);
1355 if ((xlrec->flags & SMGR_TRUNCATE_VM) != 0)
1356 BlockRefTableSetLimitBlock(brtab, &xlrec->rlocator,
1358 }
1359}
1360
1361/*
1362 * Special handling for WAL records with RM_XACT_ID.
1363 */
1364static void
1366{
1369
1370 if (xact_info == XLOG_XACT_COMMIT ||
1372 {
1375 int i;
1376
1377 /*
1378 * Don't track modified blocks for any relations that were removed on
1379 * commit.
1380 */
1382 for (i = 0; i < parsed.nrels; ++i)
1383 {
1384 ForkNumber forknum;
1385
1386 for (forknum = 0; forknum <= MAX_FORKNUM; ++forknum)
1387 if (forknum != FSM_FORKNUM)
1388 BlockRefTableSetLimitBlock(brtab, &parsed.xlocators[i],
1389 forknum, 0);
1390 }
1391 }
1392 else if (xact_info == XLOG_XACT_ABORT ||
1394 {
1397 int i;
1398
1399 /*
1400 * Don't track modified blocks for any relations that were removed on
1401 * abort.
1402 */
1404 for (i = 0; i < parsed.nrels; ++i)
1405 {
1406 ForkNumber forknum;
1407
1408 for (forknum = 0; forknum <= MAX_FORKNUM; ++forknum)
1409 if (forknum != FSM_FORKNUM)
1410 BlockRefTableSetLimitBlock(brtab, &parsed.xlocators[i],
1411 forknum, 0);
1412 }
1413 }
1414}
1415
1416/*
1417 * Special handling for WAL records with RM_XLOG_ID.
1418 *
1419 * The return value is true if WAL summarization should stop before this
1420 * record and false otherwise. When the return value is true,
1421 * *new_fast_forward indicates whether future processing should be done
1422 * in fast forward mode (i.e. read WAL without emitting summaries) or not.
1423 */
1424static bool
1426{
1428 int record_wal_level;
1429
1430 if (info == XLOG_CHECKPOINT_REDO)
1431 {
1432 /* Payload is wal_level at the time record was written. */
1434 }
1435 else if (info == XLOG_CHECKPOINT_SHUTDOWN)
1436 {
1438
1439 /* Extract wal_level at time record was written from payload. */
1441 record_wal_level = rec_ckpt.wal_level;
1442 }
1443 else if (info == XLOG_PARAMETER_CHANGE)
1444 {
1446
1447 /* Extract wal_level at time record was written from payload. */
1449 sizeof(xl_parameter_change));
1450 record_wal_level = xlrec.wal_level;
1451 }
1452 else if (info == XLOG_END_OF_RECOVERY)
1453 {
1455
1456 /* Extract wal_level at time record was written from payload. */
1458 record_wal_level = xlrec.wal_level;
1459 }
1460 else
1461 {
1462 /* No special handling required. Return false. */
1463 return false;
1464 }
1465
1466 /*
1467 * Redo can only begin at an XLOG_CHECKPOINT_REDO or
1468 * XLOG_CHECKPOINT_SHUTDOWN record, so we want WAL summarization to begin
1469 * at those points. Hence, when those records are encountered, return
1470 * true, so that we stop just before summarizing either of those records.
1471 *
1472 * We also reach here if we just saw XLOG_END_OF_RECOVERY or
1473 * XLOG_PARAMETER_CHANGE. These are not places where recovery can start,
1474 * but they're still relevant here. A new timeline can begin with
1475 * XLOG_END_OF_RECOVERY, so we need to confirm the WAL level at that
1476 * point; and a restart can provoke XLOG_PARAMETER_CHANGE after an
1477 * intervening change to postgresql.conf, which might force us to stop
1478 * summarizing.
1479 */
1481 return true;
1482}
1483
1484/*
1485 * Similar to read_local_xlog_page, but limited to read from one particular
1486 * timeline. If the end of WAL is reached, it will wait for more if reading
1487 * from the current timeline, or give up if reading from a historic timeline.
1488 * In the latter case, it will also set private_data->end_of_wal = true.
1489 *
1490 * Caller must set private_data->tli to the TLI of interest,
1491 * private_data->read_upto to the lowest LSN that is not known to be safe
1492 * to read on that timeline, and private_data->historic to true if and only
1493 * if the timeline is not the current timeline. This function will update
1494 * private_data->read_upto and private_data->historic if more WAL appears
1495 * on the current timeline or if the current timeline becomes historic.
1496 */
1497static int
1501{
1502 int count;
1504 SummarizerReadLocalXLogPrivate *private_data;
1505
1507
1508 private_data = (SummarizerReadLocalXLogPrivate *)
1509 state->private_data;
1510
1511 while (1)
1512 {
1514 {
1515 /*
1516 * more than one block available; read only that block, have
1517 * caller come back if they need more.
1518 */
1519 count = XLOG_BLCKSZ;
1520 break;
1521 }
1522 else if (targetPagePtr + reqLen > private_data->read_upto)
1523 {
1524 /* We don't seem to have enough data. */
1525 if (private_data->historic)
1526 {
1527 /*
1528 * This is a historic timeline, so there will never be any
1529 * more data than we have currently.
1530 */
1531 private_data->end_of_wal = true;
1532 return -1;
1533 }
1534 else
1535 {
1538
1539 /*
1540 * This is - or at least was up until very recently - the
1541 * current timeline, so more data might show up. Delay here
1542 * so we don't tight-loop.
1543 */
1546
1547 /* Recheck end-of-WAL. */
1549 if (private_data->tli == latest_tli)
1550 {
1551 /* Still the current timeline, update max LSN. */
1552 Assert(latest_lsn >= private_data->read_upto);
1553 private_data->read_upto = latest_lsn;
1554 }
1555 else
1556 {
1559
1560 /*
1561 * The timeline we're scanning is no longer the latest
1562 * one. Figure out when it ended.
1563 */
1564 private_data->historic = true;
1565 switchpoint = tliSwitchPoint(private_data->tli, tles,
1566 NULL);
1567
1568 /*
1569 * Allow reads up to exactly the switch point.
1570 *
1571 * It's possible that this will cause read_upto to move
1572 * backwards, because we might have been promoted before
1573 * reaching the end of the previous timeline. In that
1574 * case, the next loop iteration will likely conclude that
1575 * we've reached end of WAL.
1576 */
1577 private_data->read_upto = switchpoint;
1578
1579 /* Debugging output. */
1581 errmsg_internal("timeline %u became historic, can read up to %X/%08X",
1582 private_data->tli, LSN_FORMAT_ARGS(private_data->read_upto)));
1583 }
1584
1585 /* Go around and try again. */
1586 }
1587 }
1588 else
1589 {
1590 /* enough bytes available to satisfy the request */
1591 count = private_data->read_upto - targetPagePtr;
1592 break;
1593 }
1594 }
1595
1596 if (!WALRead(state, cur_page, targetPagePtr, count,
1597 private_data->tli, &errinfo))
1599
1600 /* Track that we read a page, for sleep time calculation. */
1602
1603 /* number of valid bytes in the buffer */
1604 return count;
1605}
1606
1607/*
1608 * Sleep for long enough that we believe it's likely that more WAL will
1609 * be available afterwards.
1610 */
1611static void
1613{
1615 {
1616 /*
1617 * No pages were read since the last sleep, so double the sleep time,
1618 * but not beyond the maximum allowable value.
1619 */
1621 }
1622 else if (pages_read_since_last_sleep > 1)
1623 {
1624 /*
1625 * Multiple pages were read since the last sleep, so reduce the sleep
1626 * time.
1627 *
1628 * A large burst of activity should be able to quickly reduce the
1629 * sleep time to the minimum, but we don't want a handful of extra WAL
1630 * records to provoke a strong reaction. We choose to reduce the sleep
1631 * time by 1 quantum for each page read beyond the first, which is a
1632 * fairly arbitrary way of trying to be reactive without overreacting.
1633 */
1635 sleep_quanta = 1;
1636 else
1638 }
1639
1640 /* Report pending statistics to the cumulative stats system. */
1641 pgstat_report_wal(false);
1642
1643 /* OK, now sleep. */
1649
1650 /* Reset count of pages read. */
1652}
1653
1654/*
1655 * Remove WAL summaries whose mtimes are older than wal_summary_keep_time.
1656 */
1657static void
1659{
1661 List *wslist;
1663
1664 /* If WAL summary removal is disabled, don't do anything. */
1665 if (wal_summary_keep_time == 0)
1666 return;
1667
1668 /*
1669 * If the redo pointer has not advanced, don't do anything.
1670 *
1671 * This has the effect that we only try to remove old WAL summary files
1672 * once per checkpoint cycle.
1673 */
1675 return;
1677
1678 /*
1679 * Files should only be removed if the last modification time precedes the
1680 * cutoff time we compute here.
1681 */
1683
1684 /* Get all the summaries that currently exist. */
1686
1687 /* Loop until all summaries have been considered for removal. */
1688 while (wslist != NIL)
1689 {
1690 ListCell *lc;
1694
1696
1697 /*
1698 * Pick a timeline for which some summary files still exist on disk,
1699 * and find the oldest LSN that still exists on disk for that
1700 * timeline.
1701 */
1704 if (oldest_segno != 0)
1706 oldest_lsn);
1707
1708
1709 /* Consider each WAL file on the selected timeline in turn. */
1710 foreach(lc, wslist)
1711 {
1713
1715
1716 /* If it's not on this timeline, it's not time to consider it. */
1717 if (selected_tli != ws->tli)
1718 continue;
1719
1720 /*
1721 * If the WAL doesn't exist any more, we can remove it if the file
1722 * modification time is old enough.
1723 */
1724 if (!XLogRecPtrIsValid(oldest_lsn) || ws->end_lsn <= oldest_lsn)
1726
1727 /*
1728 * Whether we removed the file or not, we need not consider it
1729 * again.
1730 */
1732 pfree(ws);
1733 }
1734 }
1735}
void pgaio_error_cleanup(void)
Definition aio.c:1165
void AuxiliaryProcessMainCommon(void)
Definition auxprocess.c:39
List * readTimeLineHistory(TimeLineID targetTLI)
Definition timeline.c:76
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition timeline.c:572
sigset_t UnBlockSig
Definition pqsignal.c:22
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition timestamp.c:1757
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1645
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:997
uint8_t uint8
Definition c.h:544
#define Assert(condition)
Definition c.h:873
size_t Size
Definition c.h:619
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:1931
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition elog.c:1193
int errmsg_internal(const char *fmt,...)
Definition elog.c:1170
void EmitErrorReport(void)
Definition elog.c:1704
int errcode_for_file_access(void)
Definition elog.c:886
int errdetail(const char *fmt,...)
Definition elog.c:1216
ErrorContextCallback * error_context_stack
Definition elog.c:95
void FlushErrorState(void)
Definition elog.c:1884
int errcode(int sqlerrcode)
Definition elog.c:863
int errmsg(const char *fmt,...)
Definition elog.c:1080
sigjmp_buf * PG_exception_stack
Definition elog.c:97
#define WARNING
Definition elog.h:36
#define DEBUG1
Definition elog.h:30
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
int durable_rename(const char *oldfile, const char *newfile, int elevel)
Definition fd.c:782
void AtEOXact_Files(bool isCommit)
Definition fd.c:3213
void FileClose(File file)
Definition fd.c:1965
File PathNameOpenFile(const char *fileName, int fileFlags)
Definition fd.c:1562
#define palloc0_object(type)
Definition fe_memutils.h:75
volatile sig_atomic_t LogMemoryContextPending
Definition globals.c:41
volatile sig_atomic_t ProcSignalBarrierPending
Definition globals.c:40
ProcNumber MyProcNumber
Definition globals.c:90
struct Latch * MyLatch
Definition globals.c:63
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:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
void LWLockReleaseAll(void)
Definition lwlock.c:1892
@ LW_SHARED
Definition lwlock.h:113
@ LW_EXCLUSIVE
Definition lwlock.h:112
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext TopMemoryContext
Definition mcxt.c:166
void ProcessLogMemoryContextInterrupt(void)
Definition mcxt.c:1340
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define RESUME_INTERRUPTS()
Definition miscadmin.h:136
#define AmWalSummarizerProcess()
Definition miscadmin.h:392
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
#define HOLD_INTERRUPTS()
Definition miscadmin.h:134
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
void * arg
#define MAXPGPATH
#define XLOG_CHECKPOINT_REDO
Definition pg_control.h:83
#define XLOG_CHECKPOINT_SHUTDOWN
Definition pg_control.h:69
#define XLOG_PARAMETER_CHANGE
Definition pg_control.h:75
#define XLOG_END_OF_RECOVERY
Definition pg_control.h:78
#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:391
static void * list_nth(const List *list, int n)
Definition pg_list.h:299
#define linitial(l)
Definition pg_list.h:178
void pgstat_report_wal(bool force)
Definition pgstat_wal.c:46
#define pqsignal
Definition port.h:547
#define snprintf
Definition port.h:260
uint64_t Datum
Definition postgres.h:70
static int fb(int x)
#define GetPGProcByNumber(n)
Definition proc.h:440
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
int ProcNumber
Definition procnumber.h:24
void ProcessProcSignalBarrier(void)
Definition procsignal.c:499
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition procsignal.c:677
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:1016
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
#define SMGR_TRUNCATE_VM
#define XLOG_SMGR_CREATE
#define XLOG_SMGR_TRUNCATE
#define SMGR_TRUNCATE_HEAP
Definition pg_list.h:54
RelFileNumber relNumber
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
static void pgstat_report_wait_end(void)
Definition wait_event.h:85
#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
Size WalSummarizerShmemSize(void)
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)
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)
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 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)
void WalSummarizerShmemInit(void)
static void summarizer_wait_for_wal(void)
void RemoveWalSummaryIfOlderThan(WalSummaryFile *ws, time_t cutoff_time)
Definition walsummary.c:230
List * GetWalSummaries(TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
Definition walsummary.c:43
int WriteWalSummary(void *wal_summary_io, void *data, int length)
Definition walsummary.c:294
#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:6460
XLogRecPtr GetRedoRecPtr(void)
Definition xlog.c:6563
int wal_segment_size
Definition xlog.c:146
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition xlog.c:6625
XLogSegNo XLogGetOldestSegno(TimeLineID tli)
Definition xlog.c:3811
TimeLineID GetWALInsertionTimeLineIfSet(void)
Definition xlog.c:6662
@ WAL_LEVEL_MINIMAL
Definition xlog.h:75
#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:107
bool WALRead(XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition xlogreader.c:390
void XLogReaderFree(XLogReaderState *state)
Definition xlogreader.c:162
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)
Definition xlogreader.c:232
#define XLogRecGetInfo(decoder)
Definition xlogreader.h:409
#define XLogRecGetRmid(decoder)
Definition xlogreader.h:410
#define XLogRecGetData(decoder)
Definition xlogreader.h:414
#define XL_ROUTINE(...)
Definition xlogreader.h:117
#define XLogRecMaxBlockId(decoder)
Definition xlogreader.h:417
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
static XLogReaderState * xlogreader
void wal_segment_close(XLogReaderState *state)
Definition xlogutils.c:831
void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
Definition xlogutils.c:806
void WALReadRaiseError(WALReadError *errinfo)
Definition xlogutils.c:1011