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);