Revert function to get memory context stats for processes
authorDaniel Gustafsson <dgustafsson@postgresql.org>
Fri, 23 May 2025 13:44:54 +0000 (15:44 +0200)
committerDaniel Gustafsson <dgustafsson@postgresql.org>
Fri, 23 May 2025 13:44:54 +0000 (15:44 +0200)
Due to concerns raised about the approach, and memory leaks found
in sensitive contexts the functionality is reverted. This reverts
commits 45e7e8ca9f8c115a6cd2a1ed17255ef7abf8 and 042a66291
for v18 with an intent to revisit this patch for v19.

Discussion: https://postgr.es/m/594293.1747708165@sss.pgh.pa.us

29 files changed:
doc/src/sgml/func.sgml
doc/src/sgml/release-18.sgml
src/backend/catalog/system_views.sql
src/backend/postmaster/autovacuum.c
src/backend/postmaster/checkpointer.c
src/backend/postmaster/interrupt.c
src/backend/postmaster/pgarch.c
src/backend/postmaster/startup.c
src/backend/postmaster/walsummarizer.c
src/backend/storage/ipc/ipci.c
src/backend/storage/ipc/procsignal.c
src/backend/storage/lmgr/lwlock.c
src/backend/storage/lmgr/proc.c
src/backend/tcop/postgres.c
src/backend/utils/activity/wait_event_names.txt
src/backend/utils/adt/mcxtfuncs.c
src/backend/utils/adt/pg_locale.c
src/backend/utils/init/globals.c
src/backend/utils/init/postinit.c
src/backend/utils/mb/mbutils.c
src/backend/utils/mmgr/mcxt.c
src/include/catalog/pg_proc.dat
src/include/miscadmin.h
src/include/storage/lwlock.h
src/include/storage/procsignal.h
src/include/utils/memutils.h
src/test/regress/expected/sysviews.out
src/test/regress/sql/sysviews.sql
src/tools/pgindent/typedefs.list

index b405525a465c5d95ea7fe08687116d7a54d1f9e8..c67688cbf5f98fbcb6b87a91d05bc27d2ab007ca 100644 (file)
@@ -28663,143 +28663,6 @@ acl      | {postgres=arwdDxtm/postgres,foo=r/postgres}
        </para></entry>
       </row>
 
-      <row>
-       <entry role="func_table_entry"><para role="func_signature">
-        <indexterm>
-         <primary>pg_get_process_memory_contexts</primary>
-        </indexterm>
-        <function>pg_get_process_memory_contexts</function> ( <parameter>pid</parameter> <type>integer</type>, <parameter>summary</parameter> <type>boolean</type>, <parameter>timeout</parameter> <type>float</type> )
-        <returnvalue>setof record</returnvalue>
-        ( <parameter>name</parameter> <type>text</type>,
-        <parameter>ident</parameter> <type>text</type>,
-        <parameter>type</parameter> <type>text</type>,
-        <parameter>path</parameter> <type>integer[]</type>,
-        <parameter>level</parameter> <type>integer</type>,
-        <parameter>total_bytes</parameter> <type>bigint</type>,
-        <parameter>total_nblocks</parameter> <type>bigint</type>,
-        <parameter>free_bytes</parameter> <type>bigint</type>,
-        <parameter>free_chunks</parameter> <type>bigint</type>,
-        <parameter>used_bytes</parameter> <type>bigint</type>,
-        <parameter>num_agg_contexts</parameter> <type>integer</type>,
-        <parameter>stats_timestamp</parameter> <type>timestamptz</type> )
-       </para>
-       <para>
-        This function handles requests to display the memory contexts of a
-        <productname>PostgreSQL</productname> process with the specified
-        process ID.  The function can be used to send requests to backends as
-        well as <glossterm linkend="glossary-auxiliary-proc">auxiliary processes</glossterm>.
-       </para>
-       <para>
-        The returned record contains extended statistics per each memory
-        context:
-        <itemizedlist spacing="compact">
-         <listitem>
-          <para>
-           <parameter>name</parameter> - The name of the memory context.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>ident</parameter> - Memory context ID (if any).
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>type</parameter> - The type of memory context, possible
-           values are: AllocSet, Generation, Slab and Bump.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>path</parameter> - Memory contexts are organized in a
-           tree model with TopMemoryContext as the root, and all other memory
-           contexts as nodes in the tree. The <parameter>path</parameter>
-           displays the path from the root to the current memory context. The
-           path is limited to 100 children per node, which each node limited
-           to a max depth of 100, to preserve memory during reporting. The
-           printed path will also be limited to 100 nodes counting from the
-           TopMemoryContext.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>level</parameter> - The level in the tree of the current
-           memory context.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>total_bytes</parameter> - The total number of bytes
-           allocated to this memory context.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>total_nblocks</parameter> - The total number of blocks
-           used for the allocated memory.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>free_bytes</parameter> - The amount of free memory in
-           this memory context.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>free_chunks</parameter> - The number of chunks that
-           <parameter>free_bytes</parameter> corresponds to.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>used_bytes</parameter> - The total number of bytes
-           currently occupied.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>num_agg_contexts</parameter> - The number of memory
-           contexts aggregated in the displayed statistics.
-          </para>
-         </listitem>
-         <listitem>
-          <para>
-           <parameter>stats_timestamp</parameter> - When the statistics were
-           extracted from the process.
-          </para>
-         </listitem>
-        </itemizedlist>
-       </para>
-       <para>
-        When <parameter>summary</parameter> is <literal>true</literal>, statistics
-        for memory contexts at levels 1 and 2 are displayed, with level 1
-        representing the root node (i.e., <literal>TopMemoryContext</literal>).
-        Statistics for contexts on level 2 and below are aggregates of all
-        child contexts' statistics, where <literal>num_agg_contexts</literal>
-        indicate the number aggregated child contexts.  When
-        <parameter>summary</parameter> is <literal>false</literal>,
-        <literal>the num_agg_contexts</literal> value is <literal>1</literal>,
-        indicating that individual statistics are being displayed.
-       </para>
-       <para>
-        Busy processes can delay reporting memory context statistics,
-        <parameter>timeout</parameter> specifies the number of seconds
-        to wait for updated statistics. <parameter>timeout</parameter> can be
-        specified in fractions of a second.
-       </para>
-       <para>
-        After receiving memory context statistics from the target process, it
-        returns the results as one row per context.  If all the contexts don't
-        fit within the pre-determined size limit, the remaining context
-        statistics are aggregated and a cumulative total is displayed.  The
-        <literal>num_agg_contexts</literal> column indicates the number of
-        contexts aggregated in the displayed statistics.  When
-        <literal>num_agg_contexts</literal> is <literal>1</literal> it means
-        that the context statistics are displayed separately.
-       </para></entry>
-      </row>
-
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
@@ -28939,40 +28802,6 @@ LOG:  Grand total: 1651920 bytes in 201 blocks; 622360 free (88 chunks); 1029560
     because it may generate a large number of log messages.
    </para>
 
-   <para>
-    <function>pg_get_process_memory_contexts</function> can be used to request
-    memory contexts statistics of any <productname>PostgreSQL</productname>
-    process.  For example:
-<programlisting>
-postgres=# SELECT * FROM pg_get_process_memory_contexts(
-  (SELECT pid FROM pg_stat_activity
-    WHERE backend_type = 'checkpointer'),
-  false, 0.5) LIMIT 1;
--[ RECORD 1 ]----+------------------------------
-name             | TopMemoryContext
-ident            |
-type             | AllocSet
-path             | {1}
-level            | 1
-total_bytes      | 90304
-total_nblocks    | 3
-free_bytes       | 2880
-free_chunks      | 1
-used_bytes       | 87424
-num_agg_contexts | 1
-stats_timestamp  | 2025-03-24 13:55:47.796698+01
-</programlisting>
-    <note>
-     <para>
-      While <function>pg_get_process_memory_contexts</function> can be used to
-      query memory contexts of the local backend,
-      <structname>pg_backend_memory_contexts</structname>
-      (see <xref linkend="view-pg-backend-memory-contexts"/> for more details)
-      will be less resource intensive when only the local backend is of interest.
-     </para>
-    </note>
-   </para>
-
   </sect2>
 
   <sect2 id="functions-admin-backup">
index 246e49ce74013b6985759de13dc26f63f83bce06..73523289d979c3f48d12b011d5080b7c43e01a59 100644 (file)
@@ -961,21 +961,6 @@ This is true even if the tables in different schemas have different column names
 </para>
 </listitem>
 
-<!--
-Author: Daniel Gustafsson <dgustafsson@postgresql.org>
-2025-04-08 [042a66291] Add function to get memory context stats for processes
-Author: Daniel Gustafsson <dgustafsson@postgresql.org>
-2025-04-08 [c57971034] Rename argument in pg_get_process_memory_contexts().
--->
-
-<listitem>
-<para>
-Add function pg_get_process_memory_contexts() to report process memory context statistics (Rahila Syed)
-<ulink url="&commit_baseurl;042a66291">&sect;</ulink>
-<ulink url="&commit_baseurl;c57971034">&sect;</ulink>
-</para>
-</listitem>
-
 <!--
 Author: David Rowley <drowley@postgresql.org>
 2024-07-01 [12227a1d5] Add context type field to pg_backend_memory_contexts
index 15efb02badb856f0bed36e621912b4fd6d0d15f9..08f780a2e638277971ef568cb10277ec35585ed2 100644 (file)
@@ -674,11 +674,6 @@ GRANT SELECT ON pg_backend_memory_contexts TO pg_read_all_stats;
 REVOKE EXECUTE ON FUNCTION pg_get_backend_memory_contexts() FROM PUBLIC;
 GRANT EXECUTE ON FUNCTION pg_get_backend_memory_contexts() TO pg_read_all_stats;
 
-REVOKE EXECUTE ON FUNCTION
-   pg_get_process_memory_contexts(integer, boolean, float) FROM PUBLIC;
-GRANT EXECUTE ON FUNCTION
-   pg_get_process_memory_contexts(integer, boolean, float) TO pg_read_all_stats;
-
 -- Statistics views
 
 CREATE VIEW pg_stat_all_tables AS
index 4d4a1a3197ec6543bb75997038ebe04014b2a6c9..6bcd797c36a1ff5ca56d8d86e8e5a3eedc1e87ef 100644 (file)
@@ -781,10 +781,6 @@ ProcessAutoVacLauncherInterrupts(void)
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
 
-   /* Publish memory contexts of this process */
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
-
    /* Process sinval catchup interrupts that happened while sleeping */
    ProcessCatchupInterrupt();
 }
index d3cb3f1891cea30fb7a6b42e69e4adcd276bff8a..fda91ffd1ce2dedb6942af3c74cb8a893c1e4545 100644 (file)
@@ -663,10 +663,6 @@ ProcessCheckpointerInterrupts(void)
    /* Perform logging of memory contexts of this process */
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
-
-   /* Publish memory contexts of this process */
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
 }
 
 /*
index f24f574e7485f96498530d91b606df1a5b4e8fb3..0ae9bf906ec1847aa4f63fd946f82231e7c362bf 100644 (file)
@@ -48,10 +48,6 @@ ProcessMainLoopInterrupts(void)
    /* Perform logging of memory contexts of this process */
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
-
-   /* Publish memory contexts of this process */
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
 }
 
 /*
index cb7408acf4c3d862236c3431b0b96e9e1124d51e..7e622ae4bd2a705762671eacd9b8b714edb28d7c 100644 (file)
@@ -867,10 +867,6 @@ ProcessPgArchInterrupts(void)
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
 
-   /* Publish memory contexts of this process */
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
-
    if (ConfigReloadPending)
    {
        char       *archiveLib = pstrdup(XLogArchiveLibrary);
index 7149a67fcbcd15e12d29994b1a51d37765b710b1..27e86cf393f6f95893a82cb23c1d6ed0d8145c5f 100644 (file)
@@ -192,10 +192,6 @@ ProcessStartupProcInterrupts(void)
    /* Perform logging of memory contexts of this process */
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
-
-   /* Publish memory contexts of this process */
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
 }
 
 
index c7a76711cc58f71854c723446c950f57a6e274f9..0fec4f1f871ced417fe1e8275380265d9164691f 100644 (file)
@@ -879,10 +879,6 @@ ProcessWalSummarizerInterrupts(void)
    /* Perform logging of memory contexts of this process */
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
-
-   /* Publish memory contexts of this process */
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
 }
 
 /*
index 00c76d05356717278a251bd5b41d13e06511d66d..2fa045e6b0f66ad70a59ba715cb0e09580aee57c 100644 (file)
@@ -51,7 +51,6 @@
 #include "storage/sinvaladt.h"
 #include "utils/guc.h"
 #include "utils/injection_point.h"
-#include "utils/memutils.h"
 
 /* GUCs */
 int            shared_memory_type = DEFAULT_SHARED_MEMORY_TYPE;
@@ -151,7 +150,6 @@ CalculateShmemSize(int *num_semaphores)
    size = add_size(size, InjectionPointShmemSize());
    size = add_size(size, SlotSyncShmemSize());
    size = add_size(size, AioShmemSize());
-   size = add_size(size, MemoryContextReportingShmemSize());
 
    /* include additional requested shmem from preload libraries */
    size = add_size(size, total_addin_request);
@@ -345,7 +343,6 @@ CreateOrAttachShmemStructs(void)
    WaitEventCustomShmemInit();
    InjectionPointShmemInit();
    AioShmemInit();
-   MemoryContextReportingShmemInit();
 }
 
 /*
index ce69e26d720d22dedc371977569cac8b4a8a7ead..a9bb540b55ac2c976b7d74232598347c126578e9 100644 (file)
@@ -691,9 +691,6 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
    if (CheckProcSignal(PROCSIG_LOG_MEMORY_CONTEXT))
        HandleLogMemoryContextInterrupt();
 
-   if (CheckProcSignal(PROCSIG_GET_MEMORY_CONTEXT))
-       HandleGetMemoryContextInterrupt();
-
    if (CheckProcSignal(PROCSIG_PARALLEL_APPLY_MESSAGE))
        HandleParallelApplyMessageInterrupt();
 
index 5148ef982e3810e21b6ef738fc60c9fdec7ca4c8..46f44bc45113f2deca25e03e52e20928b65e1d6a 100644 (file)
@@ -178,8 +178,6 @@ static const char *const BuiltinTrancheNames[] = {
    [LWTRANCHE_XACT_SLRU] = "XactSLRU",
    [LWTRANCHE_PARALLEL_VACUUM_DSA] = "ParallelVacuumDSA",
    [LWTRANCHE_AIO_URING_COMPLETION] = "AioUringCompletion",
-   [LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE] = "MemoryContextReportingState",
-   [LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC] = "MemoryContextReportingPerProcess",
 };
 
 StaticAssertDecl(lengthof(BuiltinTrancheNames) ==
index f194e6b3dcc83f73390e029fef3312c4238cfea6..e9ef0fbfe32cb724744e2381fbe9c89561a35dbb 100644 (file)
@@ -50,7 +50,6 @@
 #include "storage/procsignal.h"
 #include "storage/spin.h"
 #include "storage/standby.h"
-#include "utils/memutils.h"
 #include "utils/timeout.h"
 #include "utils/timestamp.h"
 
index 37784b7816de51883f9d337b343bdef6c0438088..c242c8170b56276ec1cdd468f7e083b940fe8f48 100644 (file)
@@ -3533,9 +3533,6 @@ ProcessInterrupts(void)
    if (LogMemoryContextPending)
        ProcessLogMemoryContextInterrupt();
 
-   if (PublishMemoryContextPending)
-       ProcessGetMemoryContextInterrupt();
-
    if (ParallelApplyMessagePending)
        ProcessParallelApplyMessages();
 }
index 930321905f18c27ed01e498718ef8fcb81ce2d19..5d9e04d682377d7b4e9635821e07c8225c38b987 100644 (file)
@@ -161,7 +161,6 @@ WAL_RECEIVER_EXIT   "Waiting for the WAL receiver to exit."
 WAL_RECEIVER_WAIT_START    "Waiting for startup process to send initial data for streaming replication."
 WAL_SUMMARY_READY  "Waiting for a new WAL summary to be generated."
 XACT_GROUP_UPDATE  "Waiting for the group leader to update transaction status at transaction end."
-MEM_CXT_PUBLISH    "Waiting for a process to publish memory information."
 
 ABI_compatibility:
 
index 7ec2c2250163a03210d56a39ff3faf75e104cca0..396c2f223b4e1d5a2c2cbe16a32d965505c71fed 100644 (file)
 
 #include "postgres.h"
 
-#include "access/twophase.h"
-#include "catalog/pg_authid_d.h"
 #include "funcapi.h"
 #include "mb/pg_wchar.h"
-#include "miscadmin.h"
 #include "storage/proc.h"
 #include "storage/procarray.h"
-#include "utils/acl.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/hsearch.h"
-#include "utils/memutils.h"
-#include "utils/wait_event_types.h"
 
 /* ----------
  * The max bytes for showing identifiers of MemoryContext.
  * ----------
  */
 #define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE  1024
-struct MemoryStatsBackendState *memCxtState = NULL;
-struct MemoryStatsCtl *memCxtArea = NULL;
+
+/*
+ * MemoryContextId
+ *     Used for storage of transient identifiers for
+ *     pg_get_backend_memory_contexts.
+ */
+typedef struct MemoryContextId
+{
+   MemoryContext context;
+   int         context_id;
+}          MemoryContextId;
 
 /*
  * int_list_to_array
@@ -86,7 +89,7 @@ PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore,
     */
    for (MemoryContext cur = context; cur != NULL; cur = cur->parent)
    {
-       MemoryStatsContextId *entry;
+       MemoryContextId *entry;
        bool        found;
 
        entry = hash_search(context_id_lookup, &cur, HASH_FIND, &found);
@@ -140,51 +143,36 @@ PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore,
    else
        nulls[1] = true;
 
-   type = ContextTypeToString(context->type);
-
-   values[2] = CStringGetTextDatum(type);
-   values[3] = Int32GetDatum(list_length(path));   /* level */
-   values[4] = int_list_to_array(path);
-   values[5] = Int64GetDatum(stat.totalspace);
-   values[6] = Int64GetDatum(stat.nblocks);
-   values[7] = Int64GetDatum(stat.freespace);
-   values[8] = Int64GetDatum(stat.freechunks);
-   values[9] = Int64GetDatum(stat.totalspace - stat.freespace);
-
-   tuplestore_putvalues(tupstore, tupdesc, values, nulls);
-   list_free(path);
-}
-
-/*
- * ContextTypeToString
- *     Returns a textual representation of a context type
- *
- * This should cover the same types as MemoryContextIsValid.
- */
-const char *
-ContextTypeToString(NodeTag type)
-{
-   const char *context_type;
-
-   switch (type)
+   switch (context->type)
    {
        case T_AllocSetContext:
-           context_type = "AllocSet";
+           type = "AllocSet";
            break;
        case T_GenerationContext:
-           context_type = "Generation";
+           type = "Generation";
            break;
        case T_SlabContext:
-           context_type = "Slab";
+           type = "Slab";
            break;
        case T_BumpContext:
-           context_type = "Bump";
+           type = "Bump";
            break;
        default:
-           context_type = "???";
+           type = "???";
            break;
    }
-   return context_type;
+
+   values[2] = CStringGetTextDatum(type);
+   values[3] = Int32GetDatum(list_length(path));   /* level */
+   values[4] = int_list_to_array(path);
+   values[5] = Int64GetDatum(stat.totalspace);
+   values[6] = Int64GetDatum(stat.nblocks);
+   values[7] = Int64GetDatum(stat.freespace);
+   values[8] = Int64GetDatum(stat.freechunks);
+   values[9] = Int64GetDatum(stat.totalspace - stat.freespace);
+
+   tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+   list_free(path);
 }
 
 /*
@@ -201,7 +189,7 @@ pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
    HTAB       *context_id_lookup;
 
    ctl.keysize = sizeof(MemoryContext);
-   ctl.entrysize = sizeof(MemoryStatsContextId);
+   ctl.entrysize = sizeof(MemoryContextId);
    ctl.hcxt = CurrentMemoryContext;
 
    context_id_lookup = hash_create("pg_get_backend_memory_contexts",
@@ -228,7 +216,7 @@ pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
 
    foreach_ptr(MemoryContextData, cur, contexts)
    {
-       MemoryStatsContextId *entry;
+       MemoryContextId *entry;
        bool        found;
 
        /*
@@ -236,8 +224,8 @@ pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
         * PutMemoryContextsStatsTupleStore needs this to populate the "path"
         * column with the parent context_ids.
         */
-       entry = (MemoryStatsContextId *) hash_search(context_id_lookup, &cur,
-                                                    HASH_ENTER, &found);
+       entry = (MemoryContextId *) hash_search(context_id_lookup, &cur,
+                                               HASH_ENTER, &found);
        entry->context_id = context_id++;
        Assert(!found);
 
@@ -317,349 +305,3 @@ pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)
 
    PG_RETURN_BOOL(true);
 }
-
-/*
- * pg_get_process_memory_contexts
- *     Signal a backend or an auxiliary process to send its memory contexts,
- *     wait for the results and display them.
- *
- * By default, only superusers or users with ROLE_PG_READ_ALL_STATS are allowed
- * to signal a process to return the memory contexts. This is because allowing
- * any users to issue this request at an unbounded rate would cause lots of
- * requests to be sent, which can lead to denial of service. Additional roles
- * can be permitted with GRANT.
- *
- * On receipt of this signal, a backend or an auxiliary process sets the flag
- * in the signal handler, which causes the next CHECK_FOR_INTERRUPTS()
- * or process-specific interrupt handler to copy the memory context details
- * to a dynamic shared memory space.
- *
- * We have defined a limit on DSA memory that could be allocated per process -
- * if the process has more memory contexts than what can fit in the allocated
- * size, the excess contexts are summarized and represented as cumulative total
- * at the end of the buffer.
- *
- * After sending the signal, wait on a condition variable. The publishing
- * backend, after copying the data to shared memory, sends signal on that
- * condition variable. There is one condition variable per publishing backend.
- * Once the condition variable is signalled, check if the latest memory context
- * information is available and display.
- *
- * If the publishing backend does not respond before the condition variable
- * times out, which is set to MEMSTATS_WAIT_TIMEOUT, retry given that there is
- * time left within the timeout specified by the user, before giving up and
- * returning previously published statistics, if any. If no previous statistics
- * exist, return NULL.
- */
-#define MEMSTATS_WAIT_TIMEOUT 100
-Datum
-pg_get_process_memory_contexts(PG_FUNCTION_ARGS)
-{
-   int         pid = PG_GETARG_INT32(0);
-   bool        summary = PG_GETARG_BOOL(1);
-   double      timeout = PG_GETARG_FLOAT8(2);
-   PGPROC     *proc;
-   ProcNumber  procNumber = INVALID_PROC_NUMBER;
-   bool        proc_is_aux = false;
-   ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
-   MemoryStatsEntry *memcxt_info;
-   TimestampTz start_timestamp;
-
-   /*
-    * See if the process with given pid is a backend or an auxiliary process
-    * and remember the type for when we requery the process later.
-    */
-   proc = BackendPidGetProc(pid);
-   if (proc == NULL)
-   {
-       proc = AuxiliaryPidGetProc(pid);
-       proc_is_aux = true;
-   }
-
-   /*
-    * BackendPidGetProc() and AuxiliaryPidGetProc() return NULL if the pid
-    * isn't valid; this is however not a problem and leave with a WARNING.
-    * See comment in pg_log_backend_memory_contexts for a discussion on this.
-    */
-   if (proc == NULL)
-   {
-       /*
-        * This is just a warning so a loop-through-resultset will not abort
-        * if one backend terminated on its own during the run.
-        */
-       ereport(WARNING,
-               errmsg("PID %d is not a PostgreSQL server process", pid));
-       PG_RETURN_NULL();
-   }
-
-   InitMaterializedSRF(fcinfo, 0);
-
-   procNumber = GetNumberFromPGProc(proc);
-
-   LWLockAcquire(&memCxtState[procNumber].lw_lock, LW_EXCLUSIVE);
-   memCxtState[procNumber].summary = summary;
-   LWLockRelease(&memCxtState[procNumber].lw_lock);
-
-   start_timestamp = GetCurrentTimestamp();
-
-   /*
-    * Send a signal to a PostgreSQL process, informing it we want it to
-    * produce information about its memory contexts.
-    */
-   if (SendProcSignal(pid, PROCSIG_GET_MEMORY_CONTEXT, procNumber) < 0)
-   {
-       ereport(WARNING,
-               errmsg("could not send signal to process %d: %m", pid));
-       PG_RETURN_NULL();
-   }
-
-   /*
-    * Even if the proc has published statistics, the may not be due to the
-    * current request, but previously published stats.  Check if the stats
-    * are updated by comparing the timestamp, if the stats are newer than our
-    * previously recorded timestamp from before sending the procsignal, they
-    * must by definition be updated. Wait for the timeout specified by the
-    * user, following which display old statistics if available or return
-    * NULL.
-    */
-   while (1)
-   {
-       long        msecs;
-
-       /*
-        * We expect to come out of sleep when the requested process has
-        * finished publishing the statistics, verified using the valid DSA
-        * pointer.
-        *
-        * Make sure that the information belongs to pid we requested
-        * information for, Otherwise loop back and wait for the server
-        * process to finish publishing statistics.
-        */
-       LWLockAcquire(&memCxtState[procNumber].lw_lock, LW_EXCLUSIVE);
-
-       /*
-        * Note in procnumber.h file says that a procNumber can be re-used for
-        * a different backend immediately after a backend exits. In case an
-        * old process' data was there and not updated by the current process
-        * in the slot identified by the procNumber, the pid of the requested
-        * process and the proc_id might not match.
-        */
-       if (memCxtState[procNumber].proc_id == pid)
-       {
-           /*
-            * Break if the latest stats have been read, indicated by
-            * statistics timestamp being newer than the current request
-            * timestamp.
-            */
-           msecs = TimestampDifferenceMilliseconds(start_timestamp,
-                                                   memCxtState[procNumber].stats_timestamp);
-
-           if (DsaPointerIsValid(memCxtState[procNumber].memstats_dsa_pointer)
-               && msecs > 0)
-               break;
-       }
-       LWLockRelease(&memCxtState[procNumber].lw_lock);
-
-       /*
-        * Recheck the state of the backend before sleeping on the condition
-        * variable to ensure the process is still alive.  Only check the
-        * relevant process type based on the earlier PID check.
-        */
-       if (proc_is_aux)
-           proc = AuxiliaryPidGetProc(pid);
-       else
-           proc = BackendPidGetProc(pid);
-
-       /*
-        * The process ending during memory context processing is not an
-        * error.
-        */
-       if (proc == NULL)
-       {
-           ereport(WARNING,
-                   errmsg("PID %d is no longer a PostgreSQL server process",
-                          pid));
-           PG_RETURN_NULL();
-       }
-
-       msecs = TimestampDifferenceMilliseconds(start_timestamp, GetCurrentTimestamp());
-
-       /*
-        * If we haven't already exceeded the timeout value, sleep for the
-        * remainder of the timeout on the condition variable.
-        */
-       if (msecs > 0 && msecs < (timeout * 1000))
-       {
-           /*
-            * Wait for the timeout as defined by the user. If no updated
-            * statistics are available within the allowed time then display
-            * previously published statistics if there are any. If no
-            * previous statistics are available then return NULL.  The timer
-            * is defined in milliseconds since that's what the condition
-            * variable sleep uses.
-            */
-           if (ConditionVariableTimedSleep(&memCxtState[procNumber].memcxt_cv,
-                                           ((timeout * 1000) - msecs), WAIT_EVENT_MEM_CXT_PUBLISH))
-           {
-               LWLockAcquire(&memCxtState[procNumber].lw_lock, LW_EXCLUSIVE);
-               /* Displaying previously published statistics if available */
-               if (DsaPointerIsValid(memCxtState[procNumber].memstats_dsa_pointer))
-                   break;
-               else
-               {
-                   LWLockRelease(&memCxtState[procNumber].lw_lock);
-                   PG_RETURN_NULL();
-               }
-           }
-       }
-       else
-       {
-           LWLockAcquire(&memCxtState[procNumber].lw_lock, LW_EXCLUSIVE);
-           /* Displaying previously published statistics if available */
-           if (DsaPointerIsValid(memCxtState[procNumber].memstats_dsa_pointer))
-               break;
-           else
-           {
-               LWLockRelease(&memCxtState[procNumber].lw_lock);
-               PG_RETURN_NULL();
-           }
-       }
-   }
-
-   /*
-    * We should only reach here with a valid DSA handle, either containing
-    * updated statistics or previously published statistics (identified by
-    * the timestamp.
-    */
-   Assert(memCxtArea->memstats_dsa_handle != DSA_HANDLE_INVALID);
-   /* Attach to the dsa area if we have not already done so */
-   if (MemoryStatsDsaArea == NULL)
-   {
-       MemoryContext oldcontext = CurrentMemoryContext;
-
-       MemoryContextSwitchTo(TopMemoryContext);
-       MemoryStatsDsaArea = dsa_attach(memCxtArea->memstats_dsa_handle);
-       MemoryContextSwitchTo(oldcontext);
-       dsa_pin_mapping(MemoryStatsDsaArea);
-   }
-
-   /*
-    * Backend has finished publishing the stats, project them.
-    */
-   memcxt_info = (MemoryStatsEntry *)
-       dsa_get_address(MemoryStatsDsaArea, memCxtState[procNumber].memstats_dsa_pointer);
-
-#define PG_GET_PROCESS_MEMORY_CONTEXTS_COLS    12
-   for (int i = 0; i < memCxtState[procNumber].total_stats; i++)
-   {
-       ArrayType  *path_array;
-       int         path_length;
-       Datum       values[PG_GET_PROCESS_MEMORY_CONTEXTS_COLS];
-       bool        nulls[PG_GET_PROCESS_MEMORY_CONTEXTS_COLS];
-       char       *name;
-       char       *ident;
-       Datum      *path_datum = NULL;
-       int        *path_int = NULL;
-
-       memset(values, 0, sizeof(values));
-       memset(nulls, 0, sizeof(nulls));
-
-       if (DsaPointerIsValid(memcxt_info[i].name))
-       {
-           name = (char *) dsa_get_address(MemoryStatsDsaArea, memcxt_info[i].name);
-           values[0] = CStringGetTextDatum(name);
-       }
-       else
-           nulls[0] = true;
-
-       if (DsaPointerIsValid(memcxt_info[i].ident))
-       {
-           ident = (char *) dsa_get_address(MemoryStatsDsaArea, memcxt_info[i].ident);
-           values[1] = CStringGetTextDatum(ident);
-       }
-       else
-           nulls[1] = true;
-
-       values[2] = CStringGetTextDatum(ContextTypeToString(memcxt_info[i].type));
-
-       path_length = memcxt_info[i].path_length;
-       path_datum = (Datum *) palloc(path_length * sizeof(Datum));
-       if (DsaPointerIsValid(memcxt_info[i].path))
-       {
-           path_int = (int *) dsa_get_address(MemoryStatsDsaArea, memcxt_info[i].path);
-           for (int j = 0; j < path_length; j++)
-               path_datum[j] = Int32GetDatum(path_int[j]);
-           path_array = construct_array_builtin(path_datum, path_length, INT4OID);
-           values[3] = PointerGetDatum(path_array);
-       }
-       else
-           nulls[3] = true;
-
-       values[4] = Int32GetDatum(memcxt_info[i].levels);
-       values[5] = Int64GetDatum(memcxt_info[i].totalspace);
-       values[6] = Int64GetDatum(memcxt_info[i].nblocks);
-       values[7] = Int64GetDatum(memcxt_info[i].freespace);
-       values[8] = Int64GetDatum(memcxt_info[i].freechunks);
-       values[9] = Int64GetDatum(memcxt_info[i].totalspace -
-                                 memcxt_info[i].freespace);
-       values[10] = Int32GetDatum(memcxt_info[i].num_agg_stats);
-       values[11] = TimestampTzGetDatum(memCxtState[procNumber].stats_timestamp);
-
-       tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
-                            values, nulls);
-   }
-   LWLockRelease(&memCxtState[procNumber].lw_lock);
-
-   ConditionVariableCancelSleep();
-
-   PG_RETURN_NULL();
-}
-
-Size
-MemoryContextReportingShmemSize(void)
-{
-   Size        sz = 0;
-   Size        TotalProcs = 0;
-
-   TotalProcs = add_size(TotalProcs, NUM_AUXILIARY_PROCS);
-   TotalProcs = add_size(TotalProcs, MaxBackends);
-   sz = add_size(sz, mul_size(TotalProcs, sizeof(MemoryStatsBackendState)));
-
-   sz = add_size(sz, sizeof(MemoryStatsCtl));
-
-   return sz;
-}
-
-/*
- * Initialize shared memory for displaying memory context statistics
- */
-void
-MemoryContextReportingShmemInit(void)
-{
-   bool        found;
-
-   memCxtArea = (MemoryStatsCtl *)
-       ShmemInitStruct("MemoryStatsCtl",
-                       sizeof(MemoryStatsCtl), &found);
-
-   if (!found)
-   {
-       LWLockInitialize(&memCxtArea->lw_lock, LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE);
-       memCxtArea->memstats_dsa_handle = DSA_HANDLE_INVALID;
-   }
-
-   memCxtState = (MemoryStatsBackendState *)
-       ShmemInitStruct("MemoryStatsBackendState",
-                       ((MaxBackends + NUM_AUXILIARY_PROCS) * sizeof(MemoryStatsBackendState)),
-                       &found);
-
-   if (found)
-       return;
-
-   for (int i = 0; i < (MaxBackends + NUM_AUXILIARY_PROCS); i++)
-   {
-       ConditionVariableInit(&memCxtState[i].memcxt_cv);
-       LWLockInitialize(&memCxtState[i].lw_lock, LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC);
-       memCxtState[i].memstats_dsa_pointer = InvalidDsaPointer;
-   }
-}
index a858f27cadcdd4d4f9c19ab6315b6901b1b0a438..f5e31c433a0de1b5c585c258d68adc6d7c4ad47b 100644 (file)
@@ -46,6 +46,7 @@
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
 #include "utils/pg_locale.h"
+#include "utils/relcache.h"
 #include "utils/syscache.h"
 
 #ifdef WIN32
index 92b0446b80c5c663bbc89a52f6efc3802c16d83d..d31cb45a0588aedf361219db76837d7f7b43b03c 100644 (file)
@@ -39,7 +39,6 @@ volatile sig_atomic_t TransactionTimeoutPending = false;
 volatile sig_atomic_t IdleSessionTimeoutPending = false;
 volatile sig_atomic_t ProcSignalBarrierPending = false;
 volatile sig_atomic_t LogMemoryContextPending = false;
-volatile sig_atomic_t PublishMemoryContextPending = false;
 volatile sig_atomic_t IdleStatsUpdateTimeoutPending = false;
 volatile uint32 InterruptHoldoffCount = 0;
 volatile uint32 QueryCancelHoldoffCount = 0;
index 89d72cdd5ff51adece1a87b5b1fa13152b15521a..c86ceefda940b8f2fb500786253f9f23ffea3f8d 100644 (file)
@@ -663,13 +663,6 @@ BaseInit(void)
     * drop ephemeral slots, which in turn triggers stats reporting.
     */
    ReplicationSlotInitialize();
-
-   /*
-    * The before shmem exit callback frees the DSA memory occupied by the
-    * latest memory context statistics that could be published by this proc
-    * if requested.
-    */
-   before_shmem_exit(AtProcExit_memstats_cleanup, 0);
 }
 
 
index 308016d776337d8702a12cd8280f4e7f52998053..886ecbad87183df36d970f790e1f74e1a48b428e 100644 (file)
@@ -39,6 +39,7 @@
 #include "mb/pg_wchar.h"
 #include "utils/fmgrprotos.h"
 #include "utils/memutils.h"
+#include "utils/relcache.h"
 #include "varatt.h"
 
 /*
index 7d28ca706eb559e1ca582f4f76715c3dfb0289b3..15fa4d0a55eebc00548751101a6fbfa600343b74 100644 (file)
 
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
-#include "nodes/pg_list.h"
-#include "storage/lwlock.h"
-#include "storage/ipc.h"
-#include "utils/dsa.h"
-#include "utils/hsearch.h"
 #include "utils/memdebug.h"
 #include "utils/memutils.h"
 #include "utils/memutils_internal.h"
@@ -140,17 +135,6 @@ static const MemoryContextMethods mcxt_methods[] = {
 };
 
 #undef BOGUS_MCTX
-/*
- * This is passed to MemoryContextStatsInternal to determine whether
- * to print context statistics or not and where to print them logs or
- * stderr.
- */
-typedef enum PrintDestination
-{
-   PRINT_STATS_TO_STDERR = 0,
-   PRINT_STATS_TO_LOGS,
-   PRINT_STATS_NONE
-}          PrintDestination;
 
 /*
  * CurrentMemoryContext
@@ -172,31 +156,16 @@ MemoryContext CurTransactionContext = NULL;
 
 /* This is a transient link to the active portal's memory context: */
 MemoryContext PortalContext = NULL;
-dsa_area   *MemoryStatsDsaArea = NULL;
 
 static void MemoryContextDeleteOnly(MemoryContext context);
 static void MemoryContextCallResetCallbacks(MemoryContext context);
 static void MemoryContextStatsInternal(MemoryContext context, int level,
                                       int max_level, int max_children,
                                       MemoryContextCounters *totals,
-                                      PrintDestination print_location,
-                                      int *num_contexts);
+                                      bool print_to_stderr);
 static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
                                    const char *stats_string,
                                    bool print_to_stderr);
-static void PublishMemoryContext(MemoryStatsEntry *memcxt_info,
-                                int curr_id, MemoryContext context,
-                                List *path,
-                                MemoryContextCounters stat,
-                                int num_contexts, dsa_area *area,
-                                int max_levels);
-static void compute_contexts_count_and_ids(List *contexts, HTAB *context_id_lookup,
-                                          int *stats_count,
-                                          bool summary);
-static List *compute_context_path(MemoryContext c, HTAB *context_id_lookup);
-static void free_memorycontextstate_dsa(dsa_area *area, int total_stats,
-                                       dsa_pointer prev_dsa_pointer);
-static void end_memorycontext_reporting(void);
 
 /*
  * You should not do memory allocations within a critical section, because
@@ -862,19 +831,11 @@ MemoryContextStatsDetail(MemoryContext context,
                         bool print_to_stderr)
 {
    MemoryContextCounters grand_totals;
-   int         num_contexts;
-   PrintDestination print_location;
 
    memset(&grand_totals, 0, sizeof(grand_totals));
 
-   if (print_to_stderr)
-       print_location = PRINT_STATS_TO_STDERR;
-   else
-       print_location = PRINT_STATS_TO_LOGS;
-
-   /* num_contexts report number of contexts aggregated in the output */
    MemoryContextStatsInternal(context, 1, max_level, max_children,
-                              &grand_totals, print_location, &num_contexts);
+                              &grand_totals, print_to_stderr);
 
    if (print_to_stderr)
        fprintf(stderr,
@@ -909,14 +870,13 @@ MemoryContextStatsDetail(MemoryContext context,
  *     One recursion level for MemoryContextStats
  *
  * Print stats for this context if possible, but in any case accumulate counts
- * into *totals (if not NULL). The callers should make sure that print_location
- * is set to PRINT_STATS_TO_STDERR or PRINT_STATS_TO_LOGS or PRINT_STATS_NONE.
+ * into *totals (if not NULL).
  */
 static void
 MemoryContextStatsInternal(MemoryContext context, int level,
                           int max_level, int max_children,
                           MemoryContextCounters *totals,
-                          PrintDestination print_location, int *num_contexts)
+                          bool print_to_stderr)
 {
    MemoryContext child;
    int         ichild;
@@ -924,39 +884,10 @@ MemoryContextStatsInternal(MemoryContext context, int level,
    Assert(MemoryContextIsValid(context));
 
    /* Examine the context itself */
-   switch (print_location)
-   {
-       case PRINT_STATS_TO_STDERR:
-           context->methods->stats(context,
-                                   MemoryContextStatsPrint,
-                                   &level,
-                                   totals, true);
-           break;
-
-       case PRINT_STATS_TO_LOGS:
-           context->methods->stats(context,
-                                   MemoryContextStatsPrint,
-                                   &level,
-                                   totals, false);
-           break;
-
-       case PRINT_STATS_NONE:
-
-           /*
-            * Do not print the statistics if print_location is
-            * PRINT_STATS_NONE, only compute totals. This is used in
-            * reporting of memory context statistics via a sql function. Last
-            * parameter is not relevant.
-            */
-           context->methods->stats(context,
-                                   NULL,
-                                   NULL,
-                                   totals, false);
-           break;
-   }
-
-   /* Increment the context count for each of the recursive call */
-   *num_contexts = *num_contexts + 1;
+   context->methods->stats(context,
+                           MemoryContextStatsPrint,
+                           &level,
+                           totals, print_to_stderr);
 
    /*
     * Examine children.
@@ -976,7 +907,7 @@ MemoryContextStatsInternal(MemoryContext context, int level,
            MemoryContextStatsInternal(child, level + 1,
                                       max_level, max_children,
                                       totals,
-                                      print_location, num_contexts);
+                                      print_to_stderr);
        }
    }
 
@@ -995,13 +926,7 @@ MemoryContextStatsInternal(MemoryContext context, int level,
            child = MemoryContextTraverseNext(child, context);
        }
 
-       /*
-        * Add the count of children contexts which are traversed in the
-        * non-recursive manner.
-        */
-       *num_contexts = *num_contexts + ichild;
-
-       if (print_location == PRINT_STATS_TO_STDERR)
+       if (print_to_stderr)
        {
            for (int i = 0; i < level; i++)
                fprintf(stderr, "  ");
@@ -1014,7 +939,7 @@ MemoryContextStatsInternal(MemoryContext context, int level,
                    local_totals.freechunks,
                    local_totals.totalspace - local_totals.freespace);
        }
-       else if (print_location == PRINT_STATS_TO_LOGS)
+       else
            ereport(LOG_SERVER_ONLY,
                    (errhidestmt(true),
                     errhidecontext(true),
@@ -1355,22 +1280,6 @@ HandleLogMemoryContextInterrupt(void)
    /* latch will be set by procsignal_sigusr1_handler */
 }
 
-/*
- * HandleGetMemoryContextInterrupt
- *     Handle receipt of an interrupt indicating a request to publish memory
- *     contexts statistics.
- *
- * All the actual work is deferred to ProcessGetMemoryContextInterrupt() as
- * this cannot be performed in a signal handler.
- */
-void
-HandleGetMemoryContextInterrupt(void)
-{
-   InterruptPending = true;
-   PublishMemoryContextPending = true;
-   /* latch will be set by procsignal_sigusr1_handler */
-}
-
 /*
  * ProcessLogMemoryContextInterrupt
  *         Perform logging of memory contexts of this backend process.
@@ -1408,539 +1317,6 @@ ProcessLogMemoryContextInterrupt(void)
    MemoryContextStatsDetail(TopMemoryContext, 100, 100, false);
 }
 
-/*
- * ProcessGetMemoryContextInterrupt
- *     Generate information about memory contexts used by the process.
- *
- * Performs a breadth first search on the memory context tree, thus parents
- * statistics are reported before their children in the monitoring function
- * output.
- *
- * Statistics for all the processes are shared via the same dynamic shared
- * area.  Statistics written by each process are tracked independently in
- * per-process DSA pointers. These pointers are stored in static shared memory.
- *
- * We calculate maximum number of context's statistics that can be displayed
- * using a pre-determined limit for memory available per process for this
- * utility maximum size of statistics for each context.  The remaining context
- * statistics if any are captured as a cumulative total at the end of
- * individual context's statistics.
- *
- * If summary is true, we capture the level 1 and level 2 contexts
- * statistics.  For that we traverse the memory context tree recursively in
- * depth first search manner to cover all the children of a parent context, to
- * be able to display a cumulative total of memory consumption by a parent at
- * level 2 and all its children.
- */
-void
-ProcessGetMemoryContextInterrupt(void)
-{
-   List       *contexts;
-   HASHCTL     ctl;
-   HTAB       *context_id_lookup;
-   int         context_id = 0;
-   MemoryStatsEntry *meminfo;
-   bool        summary = false;
-   int         max_stats;
-   int         idx = MyProcNumber;
-   int         stats_count = 0;
-   int         stats_num = 0;
-   MemoryContextCounters stat;
-   int         num_individual_stats = 0;
-
-   PublishMemoryContextPending = false;
-
-   /*
-    * The hash table is used for constructing "path" column of the view,
-    * similar to its local backend counterpart.
-    */
-   ctl.keysize = sizeof(MemoryContext);
-   ctl.entrysize = sizeof(MemoryStatsContextId);
-   ctl.hcxt = CurrentMemoryContext;
-
-   context_id_lookup = hash_create("pg_get_remote_backend_memory_contexts",
-                                   256,
-                                   &ctl,
-                                   HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
-
-   /* List of contexts to process in the next round - start at the top. */
-   contexts = list_make1(TopMemoryContext);
-
-   /* Compute the number of stats that can fit in the defined limit */
-   max_stats =
-       MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND / MAX_MEMORY_CONTEXT_STATS_SIZE;
-   LWLockAcquire(&memCxtState[idx].lw_lock, LW_EXCLUSIVE);
-   summary = memCxtState[idx].summary;
-   LWLockRelease(&memCxtState[idx].lw_lock);
-
-   /*
-    * Traverse the memory context tree to find total number of contexts. If
-    * summary is requested report the total number of contexts at level 1 and
-    * 2 from the top. Also, populate the hash table of context ids.
-    */
-   compute_contexts_count_and_ids(contexts, context_id_lookup, &stats_count,
-                                  summary);
-
-   /*
-    * Allocate memory in this process's DSA for storing statistics of the
-    * memory contexts upto max_stats, for contexts that don't fit within a
-    * limit, a cumulative total is written as the last record in the DSA
-    * segment.
-    */
-   stats_num = Min(stats_count, max_stats);
-
-   LWLockAcquire(&memCxtArea->lw_lock, LW_EXCLUSIVE);
-
-   /*
-    * Create a DSA and send handle to the client process after storing the
-    * context statistics. If number of contexts exceed a predefined limit
-    * (1MB), a cumulative total is stored for such contexts.
-    */
-   if (memCxtArea->memstats_dsa_handle == DSA_HANDLE_INVALID)
-   {
-       MemoryContext oldcontext = CurrentMemoryContext;
-       dsa_handle  handle;
-
-       MemoryContextSwitchTo(TopMemoryContext);
-
-       MemoryStatsDsaArea = dsa_create(memCxtArea->lw_lock.tranche);
-
-       handle = dsa_get_handle(MemoryStatsDsaArea);
-       MemoryContextSwitchTo(oldcontext);
-
-       dsa_pin_mapping(MemoryStatsDsaArea);
-
-       /*
-        * Pin the DSA area, this is to make sure the area remains attachable
-        * even if the backend that created it exits. This is done so that the
-        * statistics are published even if the process exits while a client
-        * is waiting. Also, other processes that publish statistics will use
-        * the same area.
-        */
-       dsa_pin(MemoryStatsDsaArea);
-
-       /* Set the handle in shared memory */
-       memCxtArea->memstats_dsa_handle = handle;
-   }
-
-   /*
-    * If DSA exists, created by another process publishing statistics, attach
-    * to it.
-    */
-   else if (MemoryStatsDsaArea == NULL)
-   {
-       MemoryContext oldcontext = CurrentMemoryContext;
-
-       MemoryContextSwitchTo(TopMemoryContext);
-       MemoryStatsDsaArea = dsa_attach(memCxtArea->memstats_dsa_handle);
-       MemoryContextSwitchTo(oldcontext);
-       dsa_pin_mapping(MemoryStatsDsaArea);
-   }
-   LWLockRelease(&memCxtArea->lw_lock);
-
-   /*
-    * Hold the process lock to protect writes to process specific memory. Two
-    * processes publishing statistics do not block each other.
-    */
-   LWLockAcquire(&memCxtState[idx].lw_lock, LW_EXCLUSIVE);
-   memCxtState[idx].proc_id = MyProcPid;
-
-   if (DsaPointerIsValid(memCxtState[idx].memstats_dsa_pointer))
-   {
-       /*
-        * Free any previous allocations, free the name, ident and path
-        * pointers before freeing the pointer that contains them.
-        */
-       free_memorycontextstate_dsa(MemoryStatsDsaArea, memCxtState[idx].total_stats,
-                                   memCxtState[idx].memstats_dsa_pointer);
-   }
-
-   /*
-    * Assigning total stats before allocating memory so that memory cleanup
-    * can run if any subsequent dsa_allocate call to allocate name/ident/path
-    * fails.
-    */
-   memCxtState[idx].total_stats = stats_num;
-   memCxtState[idx].memstats_dsa_pointer =
-       dsa_allocate0(MemoryStatsDsaArea, stats_num * sizeof(MemoryStatsEntry));
-
-   meminfo = (MemoryStatsEntry *)
-       dsa_get_address(MemoryStatsDsaArea, memCxtState[idx].memstats_dsa_pointer);
-
-   if (summary)
-   {
-       int         cxt_id = 0;
-       List       *path = NIL;
-
-       /* Copy TopMemoryContext statistics to DSA */
-       memset(&stat, 0, sizeof(stat));
-       (*TopMemoryContext->methods->stats) (TopMemoryContext, NULL, NULL,
-                                            &stat, true);
-       path = lcons_int(1, path);
-       PublishMemoryContext(meminfo, cxt_id, TopMemoryContext, path, stat,
-                            1, MemoryStatsDsaArea, 100);
-       cxt_id = cxt_id + 1;
-
-       /*
-        * Copy statistics for each of TopMemoryContexts children.  This
-        * includes statistics of at most 100 children per node, with each
-        * child node limited to a depth of 100 in its subtree.
-        */
-       for (MemoryContext c = TopMemoryContext->firstchild; c != NULL;
-            c = c->nextchild)
-       {
-           MemoryContextCounters grand_totals;
-           int         num_contexts = 0;
-
-           path = NIL;
-           memset(&grand_totals, 0, sizeof(grand_totals));
-
-           MemoryContextStatsInternal(c, 1, 100, 100, &grand_totals,
-                                      PRINT_STATS_NONE, &num_contexts);
-
-           path = compute_context_path(c, context_id_lookup);
-
-           /*
-            * Register the stats entry first, that way the cleanup handler
-            * can reach it in case of allocation failures of one or more
-            * members.
-            */
-           memCxtState[idx].total_stats = cxt_id++;
-           PublishMemoryContext(meminfo, cxt_id, c, path,
-                                grand_totals, num_contexts, MemoryStatsDsaArea, 100);
-       }
-       memCxtState[idx].total_stats = cxt_id;
-
-       /* Notify waiting backends and return */
-       end_memorycontext_reporting();
-
-       hash_destroy(context_id_lookup);
-
-       return;
-   }
-
-   foreach_ptr(MemoryContextData, cur, contexts)
-   {
-       List       *path = NIL;
-
-       /*
-        * Figure out the transient context_id of this context and each of its
-        * ancestors, to compute a path for this context.
-        */
-       path = compute_context_path(cur, context_id_lookup);
-
-       /* Examine the context stats */
-       memset(&stat, 0, sizeof(stat));
-       (*cur->methods->stats) (cur, NULL, NULL, &stat, true);
-
-       /* Account for saving one statistics slot for cumulative reporting */
-       if (context_id < (max_stats - 1) || stats_count <= max_stats)
-       {
-           /* Copy statistics to DSA memory */
-           PublishMemoryContext(meminfo, context_id, cur, path, stat, 1, MemoryStatsDsaArea, 100);
-       }
-       else
-       {
-           meminfo[max_stats - 1].totalspace += stat.totalspace;
-           meminfo[max_stats - 1].nblocks += stat.nblocks;
-           meminfo[max_stats - 1].freespace += stat.freespace;
-           meminfo[max_stats - 1].freechunks += stat.freechunks;
-       }
-
-       /*
-        * DSA max limit per process is reached, write aggregate of the
-        * remaining statistics.
-        *
-        * We can store contexts from 0 to max_stats - 1. When stats_count is
-        * greater than max_stats, we stop reporting individual statistics
-        * when context_id equals max_stats - 2. As we use max_stats - 1 array
-        * slot for reporting cumulative statistics or "Remaining Totals".
-        */
-       if (stats_count > max_stats && context_id == (max_stats - 2))
-       {
-           char       *nameptr;
-           int         namelen = strlen("Remaining Totals");
-
-           num_individual_stats = context_id + 1;
-           meminfo[max_stats - 1].name = dsa_allocate(MemoryStatsDsaArea, namelen + 1);
-           nameptr = dsa_get_address(MemoryStatsDsaArea, meminfo[max_stats - 1].name);
-           strlcpy(nameptr, "Remaining Totals", namelen + 1);
-           meminfo[max_stats - 1].ident = InvalidDsaPointer;
-           meminfo[max_stats - 1].path = InvalidDsaPointer;
-           meminfo[max_stats - 1].type = 0;
-       }
-       context_id++;
-   }
-
-   /*
-    * Statistics are not aggregated, i.e individual statistics reported when
-    * stats_count <= max_stats.
-    */
-   if (stats_count <= max_stats)
-   {
-       memCxtState[idx].total_stats = context_id;
-   }
-   /* Report number of aggregated memory contexts */
-   else
-   {
-       meminfo[max_stats - 1].num_agg_stats = context_id -
-           num_individual_stats;
-
-       /*
-        * Total stats equals num_individual_stats + 1 record for cumulative
-        * statistics.
-        */
-       memCxtState[idx].total_stats = num_individual_stats + 1;
-   }
-
-   /* Notify waiting backends and return */
-   end_memorycontext_reporting();
-
-   hash_destroy(context_id_lookup);
-}
-
-/*
- * Update timestamp and signal all the waiting client backends after copying
- * all the statistics.
- */
-static void
-end_memorycontext_reporting(void)
-{
-   memCxtState[MyProcNumber].stats_timestamp = GetCurrentTimestamp();
-   LWLockRelease(&memCxtState[MyProcNumber].lw_lock);
-   ConditionVariableBroadcast(&memCxtState[MyProcNumber].memcxt_cv);
-}
-
-/*
- * compute_context_path
- *
- * Append the transient context_id of this context and each of its ancestors
- * to a list, in order to compute a path.
- */
-static List *
-compute_context_path(MemoryContext c, HTAB *context_id_lookup)
-{
-   bool        found;
-   List       *path = NIL;
-   MemoryContext cur_context;
-
-   for (cur_context = c; cur_context != NULL; cur_context = cur_context->parent)
-   {
-       MemoryStatsContextId *cur_entry;
-
-       cur_entry = hash_search(context_id_lookup, &cur_context, HASH_FIND, &found);
-
-       if (!found)
-           elog(ERROR, "hash table corrupted, can't construct path value");
-
-       path = lcons_int(cur_entry->context_id, path);
-   }
-
-   return path;
-}
-
-/*
- * Return the number of contexts allocated currently by the backend
- * Assign context ids to each of the contexts.
- */
-static void
-compute_contexts_count_and_ids(List *contexts, HTAB *context_id_lookup,
-                              int *stats_count, bool summary)
-{
-   foreach_ptr(MemoryContextData, cur, contexts)
-   {
-       MemoryStatsContextId *entry;
-       bool        found;
-
-       entry = (MemoryStatsContextId *) hash_search(context_id_lookup, &cur,
-                                                    HASH_ENTER, &found);
-       Assert(!found);
-
-       /*
-        * context id starts with 1 so increment the stats_count before
-        * assigning.
-        */
-       entry->context_id = ++(*stats_count);
-
-       /* Append the children of the current context to the main list. */
-       for (MemoryContext c = cur->firstchild; c != NULL; c = c->nextchild)
-       {
-           if (summary)
-           {
-               entry = (MemoryStatsContextId *) hash_search(context_id_lookup, &c,
-                                                            HASH_ENTER, &found);
-               Assert(!found);
-
-               entry->context_id = ++(*stats_count);
-           }
-
-           contexts = lappend(contexts, c);
-       }
-
-       /*
-        * In summary mode only the first two level (from top) contexts are
-        * displayed.
-        */
-       if (summary)
-           break;
-   }
-}
-
-/*
- * PublishMemoryContext
- *
- * Copy the memory context statistics of a single context to a DSA memory
- */
-static void
-PublishMemoryContext(MemoryStatsEntry *memcxt_info, int curr_id,
-                    MemoryContext context, List *path,
-                    MemoryContextCounters stat, int num_contexts,
-                    dsa_area *area, int max_levels)
-{
-   const char *ident = context->ident;
-   const char *name = context->name;
-   int        *path_list;
-
-   /*
-    * To be consistent with logging output, we label dynahash contexts with
-    * just the hash table name as with MemoryContextStatsPrint().
-    */
-   if (context->ident && strncmp(context->name, "dynahash", 8) == 0)
-   {
-       name = context->ident;
-       ident = NULL;
-   }
-
-   if (name != NULL)
-   {
-       int         namelen = strlen(name);
-       char       *nameptr;
-
-       if (strlen(name) >= MEMORY_CONTEXT_IDENT_SHMEM_SIZE)
-           namelen = pg_mbcliplen(name, namelen,
-                                  MEMORY_CONTEXT_IDENT_SHMEM_SIZE - 1);
-
-       memcxt_info[curr_id].name = dsa_allocate(area, namelen + 1);
-       nameptr = (char *) dsa_get_address(area, memcxt_info[curr_id].name);
-       strlcpy(nameptr, name, namelen + 1);
-   }
-   else
-       memcxt_info[curr_id].name = InvalidDsaPointer;
-
-   /* Trim and copy the identifier if it is not set to NULL */
-   if (ident != NULL)
-   {
-       int         idlen = strlen(context->ident);
-       char       *identptr;
-
-       /*
-        * Some identifiers such as SQL query string can be very long,
-        * truncate oversize identifiers.
-        */
-       if (idlen >= MEMORY_CONTEXT_IDENT_SHMEM_SIZE)
-           idlen = pg_mbcliplen(ident, idlen,
-                                MEMORY_CONTEXT_IDENT_SHMEM_SIZE - 1);
-
-       memcxt_info[curr_id].ident = dsa_allocate(area, idlen + 1);
-       identptr = (char *) dsa_get_address(area, memcxt_info[curr_id].ident);
-       strlcpy(identptr, ident, idlen + 1);
-   }
-   else
-       memcxt_info[curr_id].ident = InvalidDsaPointer;
-
-   /* Allocate DSA memory for storing path information */
-   if (path == NIL)
-       memcxt_info[curr_id].path = InvalidDsaPointer;
-   else
-   {
-       int         levels = Min(list_length(path), max_levels);
-
-       memcxt_info[curr_id].path_length = levels;
-       memcxt_info[curr_id].path = dsa_allocate0(area, levels * sizeof(int));
-       memcxt_info[curr_id].levels = list_length(path);
-       path_list = (int *) dsa_get_address(area, memcxt_info[curr_id].path);
-
-       foreach_int(i, path)
-       {
-           path_list[foreach_current_index(i)] = i;
-           if (--levels == 0)
-               break;
-       }
-   }
-   memcxt_info[curr_id].type = context->type;
-   memcxt_info[curr_id].totalspace = stat.totalspace;
-   memcxt_info[curr_id].nblocks = stat.nblocks;
-   memcxt_info[curr_id].freespace = stat.freespace;
-   memcxt_info[curr_id].freechunks = stat.freechunks;
-   memcxt_info[curr_id].num_agg_stats = num_contexts;
-}
-
-/*
- * free_memorycontextstate_dsa
- *
- * Worker for freeing resources from a MemoryStatsEntry.  Callers are
- * responsible for ensuring that the DSA pointer is valid.
- */
-static void
-free_memorycontextstate_dsa(dsa_area *area, int total_stats,
-                           dsa_pointer prev_dsa_pointer)
-{
-   MemoryStatsEntry *meminfo;
-
-   meminfo = (MemoryStatsEntry *) dsa_get_address(area, prev_dsa_pointer);
-   Assert(meminfo != NULL);
-   for (int i = 0; i < total_stats; i++)
-   {
-       if (DsaPointerIsValid(meminfo[i].name))
-           dsa_free(area, meminfo[i].name);
-
-       if (DsaPointerIsValid(meminfo[i].ident))
-           dsa_free(area, meminfo[i].ident);
-
-       if (DsaPointerIsValid(meminfo[i].path))
-           dsa_free(area, meminfo[i].path);
-   }
-
-   dsa_free(area, memCxtState[MyProcNumber].memstats_dsa_pointer);
-   memCxtState[MyProcNumber].memstats_dsa_pointer = InvalidDsaPointer;
-}
-
-/*
- * Free the memory context statistics stored by this process
- * in DSA area.
- */
-void
-AtProcExit_memstats_cleanup(int code, Datum arg)
-{
-   int         idx = MyProcNumber;
-
-   if (memCxtArea->memstats_dsa_handle == DSA_HANDLE_INVALID)
-       return;
-
-   LWLockAcquire(&memCxtState[idx].lw_lock, LW_EXCLUSIVE);
-
-   if (!DsaPointerIsValid(memCxtState[idx].memstats_dsa_pointer))
-   {
-       LWLockRelease(&memCxtState[idx].lw_lock);
-       return;
-   }
-
-   /* If the dsa mapping could not be found, attach to the area */
-   if (MemoryStatsDsaArea == NULL)
-       MemoryStatsDsaArea = dsa_attach(memCxtArea->memstats_dsa_handle);
-
-   /*
-    * Free the memory context statistics, free the name, ident and path
-    * pointers before freeing the pointer that contains these pointers and
-    * integer statistics.
-    */
-   free_memorycontextstate_dsa(MemoryStatsDsaArea, memCxtState[idx].total_stats,
-                               memCxtState[idx].memstats_dsa_pointer);
-
-   dsa_detach(MemoryStatsDsaArea);
-   LWLockRelease(&memCxtState[idx].lw_lock);
-}
-
 void *
 palloc(Size size)
 {
index 62beb71da28876d346921ae3e34ed4b9ff513b3d..37a484147a8f24f67c47ee74c0dac143028c5c9a 100644 (file)
   prorettype => 'bool', proargtypes => 'int4',
   prosrc => 'pg_log_backend_memory_contexts' },
 
-# publishing memory contexts of the specified postgres process
-{ oid => '2173', descr => 'publish memory contexts of the specified backend',
-  proname => 'pg_get_process_memory_contexts', provolatile => 'v',
-  prorows => '100', proretset => 't', proparallel => 'r',
-  prorettype => 'record', proargtypes => 'int4 bool float8',
-  proallargtypes => '{int4,bool,float8,text,text,text,_int4,int4,int8,int8,int8,int8,int8,int4,timestamptz}',
-  proargmodes => '{i,i,i,o,o,o,o,o,o,o,o,o,o,o,o}',
-  proargnames => '{pid, summary, timeout, name, ident, type, path, level, total_bytes, total_nblocks, free_bytes, free_chunks, used_bytes, num_agg_contexts, stats_timestamp}',
-  prosrc => 'pg_get_process_memory_contexts' },
-
 # non-persistent series generator
 { oid => '1066', descr => 'non-persistent series generator',
   proname => 'generate_series', prorows => '1000',
index 1e59a7f910fa858049e6296b4709c50166004b28..1bef98471c363eac03e49b236803f8cf54eae95c 100644 (file)
@@ -96,7 +96,6 @@ extern PGDLLIMPORT volatile sig_atomic_t IdleSessionTimeoutPending;
 extern PGDLLIMPORT volatile sig_atomic_t ProcSignalBarrierPending;
 extern PGDLLIMPORT volatile sig_atomic_t LogMemoryContextPending;
 extern PGDLLIMPORT volatile sig_atomic_t IdleStatsUpdateTimeoutPending;
-extern PGDLLIMPORT volatile sig_atomic_t PublishMemoryContextPending;
 
 extern PGDLLIMPORT volatile sig_atomic_t CheckClientConnectionPending;
 extern PGDLLIMPORT volatile sig_atomic_t ClientConnectionLost;
index 2b4cbda39a5d8d131644d25805ae9c7c59968545..08a72569ae5fd5713af50c79d33266aa08b325aa 100644 (file)
@@ -221,8 +221,6 @@ typedef enum BuiltinTrancheIds
    LWTRANCHE_XACT_SLRU,
    LWTRANCHE_PARALLEL_VACUUM_DSA,
    LWTRANCHE_AIO_URING_COMPLETION,
-   LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE,
-   LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC,
    LWTRANCHE_FIRST_USER_DEFINED,
 }          BuiltinTrancheIds;
 
index 345d5a0ecb1eaf359b9e38e7ac24dbaf8a8a021c..afeeb1ca019f8ea35958e009bc685e1dbd009c98 100644 (file)
@@ -35,7 +35,6 @@ typedef enum
    PROCSIG_WALSND_INIT_STOPPING,   /* ask walsenders to prepare for shutdown  */
    PROCSIG_BARRIER,            /* global barrier interrupt  */
    PROCSIG_LOG_MEMORY_CONTEXT, /* ask backend to log the memory contexts */
-   PROCSIG_GET_MEMORY_CONTEXT, /* ask backend to send the memory contexts */
    PROCSIG_PARALLEL_APPLY_MESSAGE, /* Message from parallel apply workers */
 
    /* Recovery conflict reasons */
index c0987dca155fa9cd18ae8a08dca295afcbcdb29d..8abc26abce272a2b07dcf7cd507ee41f76e1b5a1 100644 (file)
@@ -18,9 +18,6 @@
 #define MEMUTILS_H
 
 #include "nodes/memnodes.h"
-#include "storage/condition_variable.h"
-#include "storage/lmgr.h"
-#include "utils/dsa.h"
 
 
 /*
 
 #define AllocHugeSizeIsValid(size) ((Size) (size) <= MaxAllocHugeSize)
 
-/*
- * Memory Context reporting size limits.
- */
-
-/* Max length of context name and ident */
-#define MEMORY_CONTEXT_IDENT_SHMEM_SIZE 64
-/* Maximum size (in bytes) of DSA area per process */
-#define MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND  ((size_t) (1 * 1024 * 1024))
-
-/*
- * Maximum size per context. Actual size may be lower as this assumes the worst
- * case of deepest path and longest identifiers (name and ident, thus the
- * multiplication by 2). The path depth is limited to 100 like for memory
- * context logging.
- */
-#define MAX_MEMORY_CONTEXT_STATS_SIZE (sizeof(MemoryStatsEntry) + \
-   (100 * sizeof(int)) + (2 * MEMORY_CONTEXT_IDENT_SHMEM_SIZE))
 
 /*
  * Standard top-level memory contexts.
@@ -339,66 +319,4 @@ pg_memory_is_all_zeros(const void *ptr, size_t len)
    return true;
 }
 
-/* Dynamic shared memory state for statistics per context */
-typedef struct MemoryStatsEntry
-{
-   dsa_pointer name;
-   dsa_pointer ident;
-   dsa_pointer path;
-   NodeTag     type;
-   int         path_length;
-   int         levels;
-   int64       totalspace;
-   int64       nblocks;
-   int64       freespace;
-   int64       freechunks;
-   int         num_agg_stats;
-} MemoryStatsEntry;
-
-/*
- * Static shared memory state representing the DSA area created for memory
- * context statistics reporting.  A single DSA area is created and used by all
- * the processes, each having its specific DSA allocations for sharing memory
- * statistics, tracked by per backend static shared memory state.
- */
-typedef struct MemoryStatsCtl
-{
-   dsa_handle  memstats_dsa_handle;
-   LWLock      lw_lock;
-} MemoryStatsCtl;
-
-/*
- * Per backend static shared memory state for memory context statistics
- * reporting.
- */
-typedef struct MemoryStatsBackendState
-{
-   ConditionVariable memcxt_cv;
-   LWLock      lw_lock;
-   int         proc_id;
-   int         total_stats;
-   bool        summary;
-   dsa_pointer memstats_dsa_pointer;
-   TimestampTz stats_timestamp;
-} MemoryStatsBackendState;
-
-
-/*
- * Used for storage of transient identifiers for pg_get_backend_memory_contexts
- */
-typedef struct MemoryStatsContextId
-{
-   MemoryContext context;
-   int         context_id;
-} MemoryStatsContextId;
-
-extern PGDLLIMPORT MemoryStatsBackendState *memCxtState;
-extern PGDLLIMPORT MemoryStatsCtl *memCxtArea;
-extern PGDLLIMPORT dsa_area *MemoryStatsDsaArea;
-extern void ProcessGetMemoryContextInterrupt(void);
-extern const char *ContextTypeToString(NodeTag type);
-extern void HandleGetMemoryContextInterrupt(void);
-extern Size MemoryContextReportingShmemSize(void);
-extern void MemoryContextReportingShmemInit(void);
-extern void AtProcExit_memstats_cleanup(int code, Datum arg);
 #endif                         /* MEMUTILS_H */
index ae17d028ed3b67ea8a8394a137464dac0fa2d287..83228cfca293fd8d30fb900d1a8d40bd354493f2 100644 (file)
@@ -232,22 +232,3 @@ select * from pg_timezone_abbrevs where abbrev = 'LMT';
  LMT    | @ 7 hours 52 mins 58 secs ago | f
 (1 row)
 
-DO $$
-DECLARE
-    bg_writer_pid int;
-    r RECORD;
-BEGIN
-        SELECT pid from pg_stat_activity where backend_type='background writer'
-    INTO bg_writer_pid;
-
-        select type, name, ident
-        from pg_get_process_memory_contexts(bg_writer_pid, false, 20)
-    where path = '{1}' into r;
-   RAISE NOTICE '%', r;
-        select type, name, ident
-        from pg_get_process_memory_contexts(pg_backend_pid(), false, 20)
-    where path = '{1}' into r;
-   RAISE NOTICE '%', r;
-END $$;
-NOTICE:  (AllocSet,TopMemoryContext,)
-NOTICE:  (AllocSet,TopMemoryContext,)
index d0917b6868eedd03015e07655e50e5ac7ef2af0c..66179f026b379d56f71084ae02c3d5ad7322da1e 100644 (file)
@@ -101,21 +101,3 @@ select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs;
 -- One specific case we can check without much fear of breakage
 -- is the historical local-mean-time value used for America/Los_Angeles.
 select * from pg_timezone_abbrevs where abbrev = 'LMT';
-
-DO $$
-DECLARE
-    bg_writer_pid int;
-    r RECORD;
-BEGIN
-        SELECT pid from pg_stat_activity where backend_type='background writer'
-    INTO bg_writer_pid;
-
-        select type, name, ident
-        from pg_get_process_memory_contexts(bg_writer_pid, false, 20)
-    where path = '{1}' into r;
-   RAISE NOTICE '%', r;
-        select type, name, ident
-        from pg_get_process_memory_contexts(pg_backend_pid(), false, 20)
-    where path = '{1}' into r;
-   RAISE NOTICE '%', r;
-END $$;
index 9ea573fae210ec067c9a9d463b3be193979346e0..a8346cda633ac6262660c64cc7c948e1f4eae2f8 100644 (file)
@@ -1674,10 +1674,6 @@ MemoryContextCounters
 MemoryContextData
 MemoryContextMethodID
 MemoryContextMethods
-MemoryStatsBackendState
-MemoryStatsContextId
-MemoryStatsCtl
-MemoryStatsEntry
 MemoryStatsPrintFunc
 MergeAction
 MergeActionState