Add new function pg_get_wal_summarizer_state().
authorRobert Haas <rhaas@postgresql.org>
Thu, 11 Jan 2024 17:41:18 +0000 (12:41 -0500)
committerRobert Haas <rhaas@postgresql.org>
Thu, 11 Jan 2024 17:41:18 +0000 (12:41 -0500)
This makes it possible to access information about the progress
of WAL summarization from SQL. The previously-added functions
pg_available_wal_summaries() and pg_wal_summary_contents() only
examine on-disk state, but this function exposes information from
the server's shared memory.

Discussion: http://postgr.es/m/CA+Tgmobvqqj-DW9F7uUzT-cQqs6wcVb-Xhs=w=hzJnXSE-kRGw@mail.gmail.com

doc/src/sgml/func.sgml
src/backend/backup/walsummaryfuncs.c
src/backend/postmaster/walsummarizer.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/include/postmaster/walsummarizer.h

index de78d58d4bc6d2bd6c69c4d059a3d060827e58ad..0f7d409e60145857425d6204bfca2c5c55bf1bc1 100644 (file)
@@ -26554,6 +26554,34 @@ SELECT collation for ('foo' COLLATE "de_DE");
         <literal>relblocknumber</literal> will be zero.
        </para></entry>
       </row>
+
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>pg_get_wal_summarizer_state</primary>
+        </indexterm>
+        <function>pg_get_wal_summarizer_state</function> ()
+        <returnvalue>record</returnvalue>
+        ( <parameter>summarized_tli</parameter> <type>bigint</type>,
+        <parameter>summarized_lsn</parameter> <type>pg_lsn</type>,
+        <parameter>pending_lsn</parameter> <type>pg_lsn</type>,
+        <parameter>summarizer_pid</parameter> <type>int</type> )
+       </para>
+       <para>
+        Returns information about the progress of the WAL summarizer. If the
+        WAL summarizer has never run since the instance was started, then
+        <literal>summarized_tli</literal> and <literal>summarized_lsn</literal>
+        will be <literal>0</literal> and <literal>0/0</literal> respectively;
+        otherwise, they will be the TLI and ending LSN of the last WAL summary
+        file written to disk. If the WAL summarizer is currently running,
+        <literal>pending_lsn</literal> will be the ending LSN of the last
+        record that it has consumed, which must always be greater than or
+        equal to <literal>summarized_lsn</literal>; if the WAL summarizer is
+        not running, it will be equal to <literal>summarized_lsn</literal>.
+        <literal>summarized_pid</literal> is the PID of the WAL summarizer
+        process, if it is running, and otherwise NULL.
+       </para></entry>
+      </row>
      </tbody>
     </tgroup>
    </table>
index 89c660c69698346cb0afa9652618f0e07c8e6cc4..f082488b33f19aa0edc0ccc5f63ee516e12128af 100644 (file)
 #include "common/blkreftable.h"
 #include "funcapi.h"
 #include "miscadmin.h"
+#include "postmaster/walsummarizer.h"
 #include "utils/fmgrprotos.h"
 #include "utils/pg_lsn.h"
 
 #define NUM_WS_ATTS            3
 #define NUM_SUMMARY_ATTS   6
+#define NUM_STATE_ATTS     4
 #define MAX_BLOCKS_PER_CALL    256
 
 /*
@@ -167,3 +169,40 @@ pg_wal_summary_contents(PG_FUNCTION_ARGS)
 
    return (Datum) 0;
 }
+
+/*
+ * Returns information about the state of the WAL summarizer process.
+ */
+Datum
+pg_get_wal_summarizer_state(PG_FUNCTION_ARGS)
+{
+   Datum       values[NUM_STATE_ATTS];
+   bool        nulls[NUM_STATE_ATTS];
+   TimeLineID  summarized_tli;
+   XLogRecPtr  summarized_lsn;
+   XLogRecPtr  pending_lsn;
+   int         summarizer_pid;
+   TupleDesc   tupdesc;
+   HeapTuple   htup;
+
+   GetWalSummarizerState(&summarized_tli, &summarized_lsn, &pending_lsn,
+                         &summarizer_pid);
+
+   if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+       elog(ERROR, "return type must be a row type");
+
+   memset(nulls, 0, sizeof(nulls));
+
+   values[0] = Int64GetDatum((int64) summarized_tli);
+   values[1] = LSNGetDatum(summarized_lsn);
+   values[2] = LSNGetDatum(pending_lsn);
+
+   if (summarizer_pid < 0)
+       nulls[3] = true;
+   else
+       values[3] = Int32GetDatum(summarizer_pid);
+
+   htup = heap_form_tuple(tupdesc, values, nulls);
+
+   PG_RETURN_DATUM(HeapTupleGetDatum(htup));
+}
index f828cc436a6dfc5955f4c243564cb590c27d7bcd..7287f07529e15d05e362e56f6a87545d267cc75e 100644 (file)
@@ -142,6 +142,7 @@ static XLogRecPtr redo_pointer_at_last_summary_removal = InvalidXLogRecPtr;
 bool       summarize_wal = false;
 int            wal_summary_keep_time = 10 * 24 * 60;
 
+static void WalSummarizerShutdown(int code, Datum arg);
 static XLogRecPtr GetLatestLSN(TimeLineID *tli);
 static void HandleWalSummarizerInterrupts(void);
 static XLogRecPtr SummarizeWAL(TimeLineID tli, XLogRecPtr start_lsn,
@@ -245,6 +246,7 @@ WalSummarizerMain(void)
    pqsignal(SIGUSR2, SIG_IGN); /* not used */
 
    /* Advertise ourselves. */
+   on_shmem_exit(WalSummarizerShutdown, (Datum) 0);
    LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
    WalSummarizerCtl->summarizer_pgprocno = MyProc->pgprocno;
    LWLockRelease(WALSummarizerLock);
@@ -417,6 +419,57 @@ WalSummarizerMain(void)
    }
 }
 
+/*
+ * Get information about the state of the WAL summarizer.
+ */
+void
+GetWalSummarizerState(TimeLineID *summarized_tli, XLogRecPtr *summarized_lsn,
+                     XLogRecPtr *pending_lsn, int *summarizer_pid)
+{
+   LWLockAcquire(WALSummarizerLock, LW_SHARED);
+   if (!WalSummarizerCtl->initialized)
+   {
+       /*
+        * If initialized is false, the rest of the structure contents are
+        * undefined.
+        */
+       *summarized_tli = 0;
+       *summarized_lsn = InvalidXLogRecPtr;
+       *pending_lsn = InvalidXLogRecPtr;
+       *summarizer_pid = -1;
+   }
+   else
+   {
+       int summarizer_pgprocno = WalSummarizerCtl->summarizer_pgprocno;
+
+       *summarized_tli = WalSummarizerCtl->summarized_tli;
+       *summarized_lsn = WalSummarizerCtl->summarized_lsn;
+       if (summarizer_pgprocno == INVALID_PGPROCNO)
+       {
+           /*
+            * If the summarizer has exited, the fact that it had processed
+            * beyond summarized_lsn is irrelevant now.
+            */
+           *pending_lsn = WalSummarizerCtl->summarized_lsn;
+           *summarizer_pid = -1;
+       }
+       else
+       {
+           *pending_lsn = WalSummarizerCtl->pending_lsn;
+
+           /*
+            * We're not fussed about inexact answers here, since they could
+            * become stale instantly, so we don't bother taking the lock, but
+            * make sure that invalid PID values are normalized to -1.
+            */
+           *summarizer_pid = GetPGProcByNumber(summarizer_pgprocno)->pid;
+           if (*summarizer_pid <= 0)
+               *summarizer_pid = -1;
+       }
+   }
+   LWLockRelease(WALSummarizerLock);
+}
+
 /*
  * Get the oldest LSN in this server's timeline history that has not yet been
  * summarized.
@@ -622,6 +675,18 @@ WaitForWalSummarization(XLogRecPtr lsn, long timeout, XLogRecPtr *pending_lsn)
    return summarized_lsn;
 }
 
+/*
+ * On exit, update shared memory to make it clear that we're no longer
+ * running.
+ */
+static void
+WalSummarizerShutdown(int code, Datum arg)
+{
+   LWLockAcquire(WALSummarizerLock, LW_EXCLUSIVE);
+   WalSummarizerCtl->summarizer_pgprocno = INVALID_PGPROCNO;
+   LWLockRelease(WALSummarizerLock);
+}
+
 /*
  * Get the latest LSN that is eligible to be summarized, and set *tli to the
  * corresponding timeline.
index 686667a0f88b808066cb57f538ac72d34f55bfcd..a94dcdc271300d38862760ac862245bd928edad8 100644 (file)
@@ -57,6 +57,6 @@
  */
 
 /*                         yyyymmddN */
-#define CATALOG_VERSION_NO 202401041
+#define CATALOG_VERSION_NO 202401111
 
 #endif
index 7979392776d467dd8ca6514e215dd29a3c851aec..58811a6530bd272cb64513d74e0394a863271cf2 100644 (file)
   proargmodes => '{i,i,i,o,o,o,o,o,o}',
   proargnames => '{tli,start_lsn,end_lsn,relfilenode,reltablespace,reldatabase,relforknumber,relblocknumber,is_limit_block}',
   prosrc => 'pg_wal_summary_contents' },
+{ oid => '8438',
+  descr => 'WAL summarizer state',
+  proname => 'pg_get_wal_summarizer_state',
+  provolatile => 'v', proparallel => 's',
+  prorettype => 'record', proargtypes => '',
+  proallargtypes => '{int8,pg_lsn,pg_lsn,int4}',
+  proargmodes => '{o,o,o,o}',
+  proargnames => '{summarized_tli,summarized_lsn,pending_lsn,summarizer_pid}',
+  prosrc => 'pg_get_wal_summarizer_state' },
 
 ]
index 75cb1d709fc470a9e569f4b68b98f776c10e7b77..d6e61b59ac7e22948ae153bd894a528733e5d246 100644 (file)
@@ -23,6 +23,10 @@ extern Size WalSummarizerShmemSize(void);
 extern void WalSummarizerShmemInit(void);
 extern void WalSummarizerMain(void) pg_attribute_noreturn();
 
+extern void GetWalSummarizerState(TimeLineID *summarized_tli,
+                                 XLogRecPtr *summarized_lsn,
+                                 XLogRecPtr *pending_lsn,
+                                 int *summarizer_pid);
 extern XLogRecPtr GetOldestUnsummarizedLSN(TimeLineID *tli,
                                           bool *lsn_is_exact,
                                           bool reset_pending_lsn);