PostgreSQL Source Code  git master
walsummarizer.h File Reference
#include "access/xlogdefs.h"
Include dependency graph for walsummarizer.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

Size WalSummarizerShmemSize (void)
 
void WalSummarizerShmemInit (void)
 
void WalSummarizerMain (char *startup_data, size_t startup_data_len) pg_attribute_noreturn()
 
void GetWalSummarizerState (TimeLineID *summarized_tli, XLogRecPtr *summarized_lsn, XLogRecPtr *pending_lsn, int *summarizer_pid)
 
XLogRecPtr GetOldestUnsummarizedLSN (TimeLineID *tli, bool *lsn_is_exact)
 
void SetWalSummarizerLatch (void)
 
void WaitForWalSummarization (XLogRecPtr lsn)
 

Variables

PGDLLIMPORT bool summarize_wal
 
PGDLLIMPORT int wal_summary_keep_time
 

Function Documentation

◆ GetOldestUnsummarizedLSN()

XLogRecPtr GetOldestUnsummarizedLSN ( TimeLineID tli,
bool lsn_is_exact 
)

Definition at line 505 of file walsummarizer.c.

506 {
507  TimeLineID latest_tli;
508  int n;
509  List *tles;
510  XLogRecPtr unsummarized_lsn = InvalidXLogRecPtr;
511  TimeLineID unsummarized_tli = 0;
512  bool should_make_exact = false;
513  List *existing_summaries;
514  ListCell *lc;
515  bool am_wal_summarizer = AmWalSummarizerProcess();
516 
517  /* If not summarizing WAL, do nothing. */
518  if (!summarize_wal)
519  return InvalidXLogRecPtr;
520 
521  /*
522  * If we are not the WAL summarizer process, then we normally just want to
523  * read the values from shared memory. However, as an exception, if shared
524  * memory hasn't been initialized yet, then we need to do that so that we
525  * can read legal values and not remove any WAL too early.
526  */
527  if (!am_wal_summarizer)
528  {
529  LWLockAcquire(WALSummarizerLock, LW_SHARED);
530 
532  {
533  unsummarized_lsn = WalSummarizerCtl->summarized_lsn;
534  if (tli != NULL)
536  if (lsn_is_exact != NULL)
537  *lsn_is_exact = WalSummarizerCtl->lsn_is_exact;
538  LWLockRelease(WALSummarizerLock);
539  return unsummarized_lsn;
540  }
541 
542  LWLockRelease(WALSummarizerLock);
543  }
544 
545  /*
546  * Find the oldest timeline on which WAL still exists, and the earliest
547  * segment for which it exists.
548  *
549  * Note that we do this every time the WAL summarizer process restarts or
550  * recovers from an error, in case the contents of pg_wal have changed
551  * under us e.g. if some files were removed, either manually - which
552  * shouldn't really happen, but might - or by postgres itself, if
553  * summarize_wal was turned off and then back on again.
554  */
555  (void) GetLatestLSN(&latest_tli);
556  tles = readTimeLineHistory(latest_tli);
557  for (n = list_length(tles) - 1; n >= 0; --n)
558  {
559  TimeLineHistoryEntry *tle = list_nth(tles, n);
560  XLogSegNo oldest_segno;
561 
562  oldest_segno = XLogGetOldestSegno(tle->tli);
563  if (oldest_segno != 0)
564  {
565  /* Compute oldest LSN that still exists on disk. */
566  XLogSegNoOffsetToRecPtr(oldest_segno, 0, wal_segment_size,
567  unsummarized_lsn);
568 
569  unsummarized_tli = tle->tli;
570  break;
571  }
572  }
573 
574  /*
575  * Don't try to summarize anything older than the end LSN of the newest
576  * summary file that exists for this timeline.
577  */
578  existing_summaries =
579  GetWalSummaries(unsummarized_tli,
581  foreach(lc, existing_summaries)
582  {
583  WalSummaryFile *ws = lfirst(lc);
584 
585  if (ws->end_lsn > unsummarized_lsn)
586  {
587  unsummarized_lsn = ws->end_lsn;
588  should_make_exact = true;
589  }
590  }
591 
592  /* It really should not be possible for us to find no WAL. */
593  if (unsummarized_tli == 0)
594  ereport(ERROR,
595  errcode(ERRCODE_INTERNAL_ERROR),
596  errmsg_internal("no WAL found on timeline %u", latest_tli));
597 
598  /*
599  * If we're the WAL summarizer, we always want to store the values we just
600  * computed into shared memory, because those are the values we're going
601  * to use to drive our operation, and so they are the authoritative
602  * values. Otherwise, we only store values into shared memory if shared
603  * memory is uninitialized. Our values are not canonical in such a case,
604  * but it's better to have something than nothing, to guide WAL retention.
605  */
606  LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
607  if (am_wal_summarizer || !WalSummarizerCtl->initialized)
608  {
610  WalSummarizerCtl->summarized_lsn = unsummarized_lsn;
611  WalSummarizerCtl->summarized_tli = unsummarized_tli;
612  WalSummarizerCtl->lsn_is_exact = should_make_exact;
613  WalSummarizerCtl->pending_lsn = unsummarized_lsn;
614  }
615  else
616  unsummarized_lsn = WalSummarizerCtl->summarized_lsn;
617 
618  /* Also return the to the caller as required. */
619  if (tli != NULL)
621  if (lsn_is_exact != NULL)
622  *lsn_is_exact = WalSummarizerCtl->lsn_is_exact;
623  LWLockRelease(WALSummarizerLock);
624 
625  return unsummarized_lsn;
626 }
List * readTimeLineHistory(TimeLineID targetTLI)
Definition: timeline.c:76
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode(int sqlerrcode)
Definition: elog.c:853
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1168
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1781
@ LW_SHARED
Definition: lwlock.h:115
@ LW_EXCLUSIVE
Definition: lwlock.h:114
#define AmWalSummarizerProcess()
Definition: miscadmin.h:384
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
static void * list_nth(const List *list, int n)
Definition: pg_list.h:299
Definition: pg_list.h:54
TimeLineID tli
Definition: timeline.h:27
XLogRecPtr summarized_lsn
Definition: walsummarizer.c:84
TimeLineID summarized_tli
Definition: walsummarizer.c:83
XLogRecPtr pending_lsn
Definition: walsummarizer.c:87
XLogRecPtr end_lsn
Definition: walsummary.h:30
static XLogRecPtr GetLatestLSN(TimeLineID *tli)
static WalSummarizerData * WalSummarizerCtl
bool summarize_wal
List * GetWalSummaries(TimeLineID tli, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
Definition: walsummary.c:43
int wal_segment_size
Definition: xlog.c:141
XLogSegNo XLogGetOldestSegno(TimeLineID tli)
Definition: xlog.c:3766
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
uint32 TimeLineID
Definition: xlogdefs.h:59
uint64 XLogSegNo
Definition: xlogdefs.h:48

References AmWalSummarizerProcess, WalSummaryFile::end_lsn, ereport, errcode(), errmsg_internal(), ERROR, GetLatestLSN(), GetWalSummaries(), WalSummarizerData::initialized, InvalidXLogRecPtr, lfirst, list_length(), list_nth(), WalSummarizerData::lsn_is_exact, LW_EXCLUSIVE, LW_SHARED, LWLockAcquire(), LWLockRelease(), WalSummarizerData::pending_lsn, readTimeLineHistory(), summarize_wal, WalSummarizerData::summarized_lsn, WalSummarizerData::summarized_tli, TimeLineHistoryEntry::tli, wal_segment_size, WalSummarizerCtl, XLogGetOldestSegno(), and XLogSegNoOffsetToRecPtr.

Referenced by KeepLogSeg(), and WalSummarizerMain().

◆ GetWalSummarizerState()

void GetWalSummarizerState ( TimeLineID summarized_tli,
XLogRecPtr summarized_lsn,
XLogRecPtr pending_lsn,
int *  summarizer_pid 
)

Definition at line 447 of file walsummarizer.c.

449 {
450  LWLockAcquire(WALSummarizerLock, LW_SHARED);
452  {
453  /*
454  * If initialized is false, the rest of the structure contents are
455  * undefined.
456  */
457  *summarized_tli = 0;
458  *summarized_lsn = InvalidXLogRecPtr;
459  *pending_lsn = InvalidXLogRecPtr;
460  *summarizer_pid = -1;
461  }
462  else
463  {
464  int summarizer_pgprocno = WalSummarizerCtl->summarizer_pgprocno;
465 
466  *summarized_tli = WalSummarizerCtl->summarized_tli;
467  *summarized_lsn = WalSummarizerCtl->summarized_lsn;
468  if (summarizer_pgprocno == INVALID_PROC_NUMBER)
469  {
470  /*
471  * If the summarizer has exited, the fact that it had processed
472  * beyond summarized_lsn is irrelevant now.
473  */
474  *pending_lsn = WalSummarizerCtl->summarized_lsn;
475  *summarizer_pid = -1;
476  }
477  else
478  {
479  *pending_lsn = WalSummarizerCtl->pending_lsn;
480 
481  /*
482  * We're not fussed about inexact answers here, since they could
483  * become stale instantly, so we don't bother taking the lock, but
484  * make sure that invalid PID values are normalized to -1.
485  */
486  *summarizer_pid = GetPGProcByNumber(summarizer_pgprocno)->pid;
487  if (*summarizer_pid <= 0)
488  *summarizer_pid = -1;
489  }
490  }
491  LWLockRelease(WALSummarizerLock);
492 }
#define GetPGProcByNumber(n)
Definition: proc.h:427
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
ProcNumber summarizer_pgprocno
Definition: walsummarizer.c:86

References GetPGProcByNumber, WalSummarizerData::initialized, INVALID_PROC_NUMBER, InvalidXLogRecPtr, LW_SHARED, LWLockAcquire(), LWLockRelease(), WalSummarizerData::pending_lsn, WalSummarizerData::summarized_lsn, WalSummarizerData::summarized_tli, WalSummarizerData::summarizer_pgprocno, and WalSummarizerCtl.

Referenced by pg_get_wal_summarizer_state().

◆ SetWalSummarizerLatch()

void SetWalSummarizerLatch ( void  )

Definition at line 637 of file walsummarizer.c.

638 {
639  ProcNumber pgprocno;
640 
641  if (WalSummarizerCtl == NULL)
642  return;
643 
644  LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
646  LWLockRelease(WALSummarizerLock);
647 
648  if (pgprocno != INVALID_PROC_NUMBER)
649  SetLatch(&ProcGlobal->allProcs[pgprocno].procLatch);
650 }
void SetLatch(Latch *latch)
Definition: latch.c:632
int ProcNumber
Definition: procnumber.h:24
PROC_HDR * ProcGlobal
Definition: proc.c:78
Latch procLatch
Definition: proc.h:164
PGPROC * allProcs
Definition: proc.h:379

References PROC_HDR::allProcs, INVALID_PROC_NUMBER, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), ProcGlobal, PGPROC::procLatch, SetLatch(), WalSummarizerData::summarizer_pgprocno, and WalSummarizerCtl.

Referenced by CreateCheckPoint().

◆ WaitForWalSummarization()

void WaitForWalSummarization ( XLogRecPtr  lsn)

Definition at line 660 of file walsummarizer.c.

661 {
662  TimestampTz initial_time,
663  cycle_time,
664  current_time;
665  XLogRecPtr prior_pending_lsn = InvalidXLogRecPtr;
666  int deadcycles = 0;
667 
668  initial_time = cycle_time = GetCurrentTimestamp();
669 
670  while (1)
671  {
672  long timeout_in_ms = 10000;
673  XLogRecPtr summarized_lsn;
674  XLogRecPtr pending_lsn;
675 
677 
678  /* If WAL summarization is disabled while we're waiting, give up. */
679  if (!summarize_wal)
680  return;
681 
682  /*
683  * If the LSN summarized on disk has reached the target value, stop.
684  */
685  LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
686  summarized_lsn = WalSummarizerCtl->summarized_lsn;
687  pending_lsn = WalSummarizerCtl->pending_lsn;
688  LWLockRelease(WALSummarizerLock);
689 
690  /* If WAL summarization has progressed sufficiently, stop waiting. */
691  if (summarized_lsn >= lsn)
692  break;
693 
694  /* Recheck current time. */
695  current_time = GetCurrentTimestamp();
696 
697  /* Have we finished the current cycle of waiting? */
698  if (TimestampDifferenceMilliseconds(cycle_time,
699  current_time) >= timeout_in_ms)
700  {
701  long elapsed_seconds;
702 
703  /* Begin new wait cycle. */
704  cycle_time = TimestampTzPlusMilliseconds(cycle_time,
705  timeout_in_ms);
706 
707  /*
708  * Keep track of the number of cycles during which there has been
709  * no progression of pending_lsn. If pending_lsn is not advancing,
710  * that means that not only are no new files appearing on disk,
711  * but we're not even incorporating new records into the in-memory
712  * state.
713  */
714  if (pending_lsn > prior_pending_lsn)
715  {
716  prior_pending_lsn = pending_lsn;
717  deadcycles = 0;
718  }
719  else
720  ++deadcycles;
721 
722  /*
723  * If we've managed to wait for an entire minute without the WAL
724  * summarizer absorbing a single WAL record, error out; probably
725  * something is wrong.
726  *
727  * We could consider also erroring out if the summarizer is taking
728  * too long to catch up, but it's not clear what rate of progress
729  * would be acceptable and what would be too slow. So instead, we
730  * just try to error out in the case where there's no progress at
731  * all. That seems likely to catch a reasonable number of the
732  * things that can go wrong in practice (e.g. the summarizer
733  * process is completely hung, say because somebody hooked up a
734  * debugger to it or something) without giving up too quickly when
735  * the system is just slow.
736  */
737  if (deadcycles >= 6)
738  ereport(ERROR,
739  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
740  errmsg("WAL summarization is not progressing"),
741  errdetail("Summarization is needed through %X/%X, but is stuck at %X/%X on disk and %X/%X in memory.",
742  LSN_FORMAT_ARGS(lsn),
743  LSN_FORMAT_ARGS(summarized_lsn),
744  LSN_FORMAT_ARGS(pending_lsn))));
745 
746 
747  /*
748  * Otherwise, just let the user know what's happening.
749  */
750  elapsed_seconds =
751  TimestampDifferenceMilliseconds(initial_time,
752  current_time) / 1000;
754  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
755  errmsg("still waiting for WAL summarization through %X/%X after %ld seconds",
756  LSN_FORMAT_ARGS(lsn),
757  elapsed_seconds),
758  errdetail("Summarization has reached %X/%X on disk and %X/%X in memory.",
759  LSN_FORMAT_ARGS(summarized_lsn),
760  LSN_FORMAT_ARGS(pending_lsn))));
761  }
762 
763  /*
764  * Align the wait time to prevent drift. This doesn't really matter,
765  * but we'd like the warnings about how long we've been waiting to say
766  * 10 seconds, 20 seconds, 30 seconds, 40 seconds ... without ever
767  * drifting to something that is not a multiple of ten.
768  */
769  timeout_in_ms -=
770  TimestampDifferenceMilliseconds(cycle_time, current_time);
771 
772  /* Wait and see. */
774  timeout_in_ms,
775  WAIT_EVENT_WAL_SUMMARY_READY);
776  }
777 
779 }
long TimestampDifferenceMilliseconds(TimestampTz start_time, TimestampTz stop_time)
Definition: timestamp.c:1767
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1655
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
int64 TimestampTz
Definition: timestamp.h:39
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define WARNING
Definition: elog.h:36
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
ConditionVariable summary_file_cv
Definition: walsummarizer.c:92
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:85
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43

References CHECK_FOR_INTERRUPTS, ConditionVariableCancelSleep(), ConditionVariableTimedSleep(), ereport, errcode(), errdetail(), errmsg(), ERROR, GetCurrentTimestamp(), InvalidXLogRecPtr, LSN_FORMAT_ARGS, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), WalSummarizerData::pending_lsn, summarize_wal, WalSummarizerData::summarized_lsn, WalSummarizerData::summary_file_cv, TimestampDifferenceMilliseconds(), TimestampTzPlusMilliseconds, WalSummarizerCtl, and WARNING.

Referenced by CleanupAfterArchiveRecovery(), and PrepareForIncrementalBackup().

◆ WalSummarizerMain()

void WalSummarizerMain ( char *  startup_data,
size_t  startup_data_len 
)

Definition at line 211 of file walsummarizer.c.

212 {
213  sigjmp_buf local_sigjmp_buf;
215 
216  /*
217  * Within this function, 'current_lsn' and 'current_tli' refer to the
218  * point from which the next WAL summary file should start. 'exact' is
219  * true if 'current_lsn' is known to be the start of a WAL record or WAL
220  * segment, and false if it might be in the middle of a record someplace.
221  *
222  * 'switch_lsn' and 'switch_tli', if set, are the LSN at which we need to
223  * switch to a new timeline and the timeline to which we need to switch.
224  * If not set, we either haven't figured out the answers yet or we're
225  * already on the latest timeline.
226  */
227  XLogRecPtr current_lsn;
228  TimeLineID current_tli;
229  bool exact;
230  XLogRecPtr switch_lsn = InvalidXLogRecPtr;
231  TimeLineID switch_tli = 0;
232 
233  Assert(startup_data_len == 0);
234 
237 
238  ereport(DEBUG1,
239  (errmsg_internal("WAL summarizer started")));
240 
241  /*
242  * Properly accept or ignore signals the postmaster might send us
243  *
244  * We have no particular use for SIGINT at the moment, but seems
245  * reasonable to treat like SIGTERM.
246  */
250  /* SIGQUIT handler was already set up by InitPostmasterChild */
254  pqsignal(SIGUSR2, SIG_IGN); /* not used */
255 
256  /* Advertise ourselves. */
258  LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
260  LWLockRelease(WALSummarizerLock);
261 
262  /* Create and switch to a memory context that we can reset on error. */
264  "Wal Summarizer",
267 
268  /*
269  * Reset some signals that are accepted by postmaster but not here
270  */
272 
273  /*
274  * If an exception is encountered, processing resumes here.
275  */
276  if (sigsetjmp(local_sigjmp_buf, 1) != 0)
277  {
278  /* Since not using PG_TRY, must reset error stack by hand */
279  error_context_stack = NULL;
280 
281  /* Prevent interrupts while cleaning up */
282  HOLD_INTERRUPTS();
283 
284  /* Report the error to the server log */
285  EmitErrorReport();
286 
287  /* 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  */
300  FlushErrorState();
301 
302  /* Flush any leaked data in the top-level 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  */
318  (void) WaitLatch(MyLatch,
320  10000,
321  WAIT_EVENT_WAL_SUMMARIZER_ERROR);
322  }
323 
324  /* We can now handle ereport(ERROR) */
325  PG_exception_stack = &local_sigjmp_buf;
326 
327  /*
328  * Unblock signals (they were blocked when the postmaster forked us)
329  */
330  sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
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  */
341  current_lsn = GetOldestUnsummarizedLSN(&current_tli, &exact);
342  if (XLogRecPtrIsInvalid(current_lsn))
343  proc_exit(0);
344 
345  /*
346  * Loop forever
347  */
348  for (;;)
349  {
350  XLogRecPtr latest_lsn;
351  TimeLineID latest_tli;
352  XLogRecPtr end_of_summary_lsn;
353 
354  /* Flush any leaked data in the top-level context */
356 
357  /* Process any signals received recently. */
359 
360  /* If it's time to remove any old WAL summaries, do that now. */
362 
363  /* Find the LSN and TLI up to which we can safely summarize. */
364  latest_lsn = GetLatestLSN(&latest_tli);
365 
366  /*
367  * If we're summarizing a historic timeline and we haven't yet
368  * computed the point at which to switch to the next timeline, do that
369  * now.
370  *
371  * Note that if this is a standby, what was previously the current
372  * timeline could become historic at any time.
373  *
374  * We could try to make this more efficient by caching the results of
375  * readTimeLineHistory when latest_tli has not changed, but since we
376  * only have to do this once per timeline switch, we probably wouldn't
377  * save any significant amount of work in practice.
378  */
379  if (current_tli != latest_tli && XLogRecPtrIsInvalid(switch_lsn))
380  {
381  List *tles = readTimeLineHistory(latest_tli);
382 
383  switch_lsn = tliSwitchPoint(current_tli, tles, &switch_tli);
384  ereport(DEBUG1,
385  errmsg("switch point from TLI %u to TLI %u is at %X/%X",
386  current_tli, switch_tli, LSN_FORMAT_ARGS(switch_lsn)));
387  }
388 
389  /*
390  * If we've reached the switch LSN, we can't summarize anything else
391  * on this timeline. Switch to the next timeline and go around again,
392  * backing up to the exact switch point if we passed it.
393  */
394  if (!XLogRecPtrIsInvalid(switch_lsn) && current_lsn >= switch_lsn)
395  {
396  /* Restart summarization from switch point. */
397  current_tli = switch_tli;
398  current_lsn = switch_lsn;
399 
400  /* Next timeline and switch point, if any, not yet known. */
401  switch_lsn = InvalidXLogRecPtr;
402  switch_tli = 0;
403 
404  /* Update (really, rewind, if needed) state in shared memory. */
405  LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
406  WalSummarizerCtl->summarized_lsn = current_lsn;
407  WalSummarizerCtl->summarized_tli = current_tli;
409  WalSummarizerCtl->pending_lsn = current_lsn;
410  LWLockRelease(WALSummarizerLock);
411 
412  continue;
413  }
414 
415  /* Summarize WAL. */
416  end_of_summary_lsn = SummarizeWAL(current_tli,
417  current_lsn, exact,
418  switch_lsn, latest_lsn);
419  Assert(!XLogRecPtrIsInvalid(end_of_summary_lsn));
420  Assert(end_of_summary_lsn >= current_lsn);
421 
422  /*
423  * Update state for next loop iteration.
424  *
425  * Next summary file should start from exactly where this one ended.
426  */
427  current_lsn = end_of_summary_lsn;
428  exact = true;
429 
430  /* Update state in shared memory. */
431  LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
432  WalSummarizerCtl->summarized_lsn = end_of_summary_lsn;
433  WalSummarizerCtl->summarized_tli = current_tli;
435  WalSummarizerCtl->pending_lsn = end_of_summary_lsn;
436  LWLockRelease(WALSummarizerLock);
437 
438  /* Wake up anyone waiting for more summary files to be written. */
440  }
441 }
void AuxiliaryProcessMainCommon(void)
Definition: auxprocess.c:44
XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)
Definition: timeline.c:572
sigset_t UnBlockSig
Definition: pqsignal.c:22
#define Assert(condition)
Definition: c.h:858
void ConditionVariableBroadcast(ConditionVariable *cv)
void AtEOXact_HashTables(bool isCommit)
Definition: dynahash.c:1869
void EmitErrorReport(void)
Definition: elog.c:1670
ErrorContextCallback * error_context_stack
Definition: elog.c:94
void FlushErrorState(void)
Definition: elog.c:1850
sigjmp_buf * PG_exception_stack
Definition: elog.c:96
#define DEBUG1
Definition: elog.h:30
void AtEOXact_Files(bool isCommit)
Definition: fd.c:3165
ProcNumber MyProcNumber
Definition: globals.c:88
struct Latch * MyLatch
Definition: globals.c:61
void SignalHandlerForShutdownRequest(SIGNAL_ARGS)
Definition: interrupt.c:105
void SignalHandlerForConfigReload(SIGNAL_ARGS)
Definition: interrupt.c:61
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:365
void proc_exit(int code)
Definition: ipc.c:104
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:517
#define WL_TIMEOUT
Definition: latch.h:130
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
void LWLockReleaseAll(void)
Definition: lwlock.c:1876
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
MemoryContext TopMemoryContext
Definition: mcxt.c:149
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:135
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:133
@ B_WAL_SUMMARIZER
Definition: miscadmin.h:360
BackendType MyBackendType
Definition: miscinit.c:63
pqsigfunc pqsignal(int signo, pqsigfunc func)
uintptr_t Datum
Definition: postgres.h:64
void procsignal_sigusr1_handler(SIGNAL_ARGS)
Definition: procsignal.c:635
tree context
Definition: radixtree.h:1835
MemoryContextSwitchTo(old_ctx)
void ReleaseAuxProcessResources(bool isCommit)
Definition: resowner.c:1002
static void pgstat_report_wait_end(void)
Definition: wait_event.h:101
static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn, bool exact, XLogRecPtr switch_lsn, XLogRecPtr maximum_lsn)
static void HandleWalSummarizerInterrupts(void)
static void WalSummarizerShutdown(int code, Datum arg)
static void MaybeRemoveOldWalSummaries(void)
XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli, bool *lsn_is_exact)
#define SIGCHLD
Definition: win32_port.h:178
#define SIGHUP
Definition: win32_port.h:168
#define SIG_DFL
Definition: win32_port.h:163
#define SIGPIPE
Definition: win32_port.h:173
#define SIGUSR1
Definition: win32_port.h:180
#define SIGALRM
Definition: win32_port.h:174
#define SIGUSR2
Definition: win32_port.h:181
#define SIG_IGN
Definition: win32_port.h:165
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, AtEOXact_Files(), AtEOXact_HashTables(), AuxiliaryProcessMainCommon(), B_WAL_SUMMARIZER, ConditionVariableBroadcast(), ConditionVariableCancelSleep(), context, DEBUG1, EmitErrorReport(), ereport, errmsg(), errmsg_internal(), error_context_stack, FlushErrorState(), GetLatestLSN(), GetOldestUnsummarizedLSN(), HandleWalSummarizerInterrupts(), HOLD_INTERRUPTS, InvalidXLogRecPtr, LSN_FORMAT_ARGS, WalSummarizerData::lsn_is_exact, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), LWLockReleaseAll(), MaybeRemoveOldWalSummaries(), MemoryContextReset(), MemoryContextSwitchTo(), MyBackendType, MyLatch, MyProcNumber, on_shmem_exit(), WalSummarizerData::pending_lsn, PG_exception_stack, pgstat_report_wait_end(), pqsignal(), proc_exit(), procsignal_sigusr1_handler(), readTimeLineHistory(), ReleaseAuxProcessResources(), RESUME_INTERRUPTS, SIG_DFL, SIG_IGN, SIGALRM, SIGCHLD, SIGHUP, SignalHandlerForConfigReload(), SignalHandlerForShutdownRequest(), SIGPIPE, SIGUSR1, SIGUSR2, WalSummarizerData::summarized_lsn, WalSummarizerData::summarized_tli, WalSummarizerData::summarizer_pgprocno, SummarizeWAL(), WalSummarizerData::summary_file_cv, tliSwitchPoint(), TopMemoryContext, UnBlockSig, WaitLatch(), WalSummarizerCtl, WalSummarizerShutdown(), WL_EXIT_ON_PM_DEATH, WL_TIMEOUT, and XLogRecPtrIsInvalid.

◆ WalSummarizerShmemInit()

void WalSummarizerShmemInit ( void  )

Definition at line 180 of file walsummarizer.c.

181 {
182  bool found;
183 
185  ShmemInitStruct("Wal Summarizer Ctl", WalSummarizerShmemSize(),
186  &found);
187 
188  if (!found)
189  {
190  /*
191  * First time through, so initialize.
192  *
193  * We're just filling in dummy values here -- the real initialization
194  * will happen when GetOldestUnsummarizedLSN() is called for the first
195  * time.
196  */
197  WalSummarizerCtl->initialized = false;
204  }
205 }
void ConditionVariableInit(ConditionVariable *cv)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:387
Size WalSummarizerShmemSize(void)

References ConditionVariableInit(), WalSummarizerData::initialized, INVALID_PROC_NUMBER, InvalidXLogRecPtr, WalSummarizerData::lsn_is_exact, WalSummarizerData::pending_lsn, ShmemInitStruct(), WalSummarizerData::summarized_lsn, WalSummarizerData::summarized_tli, WalSummarizerData::summarizer_pgprocno, WalSummarizerData::summary_file_cv, WalSummarizerCtl, and WalSummarizerShmemSize().

Referenced by CreateOrAttachShmemStructs().

◆ WalSummarizerShmemSize()

Size WalSummarizerShmemSize ( void  )

Definition at line 171 of file walsummarizer.c.

172 {
173  return sizeof(WalSummarizerData);
174 }

Referenced by CalculateShmemSize(), and WalSummarizerShmemInit().

Variable Documentation

◆ summarize_wal

◆ wal_summary_keep_time

PGDLLIMPORT int wal_summary_keep_time
extern

Definition at line 143 of file walsummarizer.c.

Referenced by MaybeRemoveOldWalSummaries().