Hi,

On 2014-05-04 13:44:17 +0200, Andres Freund wrote:
> postgres=# SELECT * FROM pg_shmem_allocations ORDER BY size DESC;
>                  key                 |     off     |    size     | allocated
> -------------------------------------+-------------+-------------+-----------
>  Buffer Blocks                       |   286242528 | 17179869184 | t
>  Buffer Descriptors                  |   152024800 |   134217728 | t

Abhijit notified me that I've attached the wrong patch. Corrected.

Greetings,

Andres Freund

-- 
 Andres Freund                     http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
>From e8a7576f3a593f4f88bd619ae2504ee320e61db2 Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Sun, 4 May 2014 13:37:20 +0200
Subject: [PATCH] Add pg_shmem_allocations view.

---
 src/backend/catalog/system_views.sql |  3 ++
 src/backend/storage/ipc/shmem.c      | 97 ++++++++++++++++++++++++++++++++++++
 src/include/catalog/pg_proc.h        |  2 +
 src/include/utils/builtins.h         |  3 ++
 src/test/regress/expected/rules.out  |  5 ++
 5 files changed, 110 insertions(+)

diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 42a4c00..104491a 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -387,6 +387,9 @@ CREATE VIEW pg_timezone_abbrevs AS
 CREATE VIEW pg_timezone_names AS
     SELECT * FROM pg_timezone_names();
 
+CREATE VIEW pg_shmem_allocations AS
+    SELECT * FROM pg_get_shmem_allocations();
+
 -- Statistics views
 
 CREATE VIEW pg_stat_all_tables AS
diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c
index 1d27a89..5722c78 100644
--- a/src/backend/storage/ipc/shmem.c
+++ b/src/backend/storage/ipc/shmem.c
@@ -66,11 +66,14 @@
 #include "postgres.h"
 
 #include "access/transam.h"
+#include "fmgr.h"
+#include "funcapi.h"
 #include "miscadmin.h"
 #include "storage/lwlock.h"
 #include "storage/pg_shmem.h"
 #include "storage/shmem.h"
 #include "storage/spin.h"
+#include "utils/builtins.h"
 
 
 /* shared memory global variables */
@@ -459,3 +462,97 @@ mul_size(Size s1, Size s2)
 				 errmsg("requested shared memory size overflows size_t")));
 	return result;
 }
+
+/* SQL SRF showing allocated shared memory */
+Datum
+pg_get_shmem_allocations(PG_FUNCTION_ARGS)
+{
+#define PG_GET_SHMEM_SIZES_COLS 4
+
+	ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+	TupleDesc	tupdesc;
+	Tuplestorestate *tupstore;
+	MemoryContext per_query_ctx;
+	MemoryContext oldcontext;
+	HASH_SEQ_STATUS hstat;
+	ShmemIndexEnt *ent;
+
+	/* check to see if caller supports us returning a tuplestore */
+	if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("set-valued function called in context that cannot accept a set")));
+	if (!(rsinfo->allowedModes & SFRM_Materialize))
+		ereport(ERROR,
+				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+				 errmsg("materialize mode required, but it is not " \
+						"allowed in this context")));
+
+	/* Build a tuple descriptor for our result type */
+	if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+		elog(ERROR, "return type must be a row type");
+
+	per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+	oldcontext = MemoryContextSwitchTo(per_query_ctx);
+
+	tupstore = tuplestore_begin_heap(true, false, work_mem);
+	rsinfo->returnMode = SFRM_Materialize;
+	rsinfo->setResult = tupstore;
+	rsinfo->setDesc = tupdesc;
+
+	MemoryContextSwitchTo(oldcontext);
+
+	hash_seq_init(&hstat, ShmemIndex);
+
+	/* output all allocated entries */
+	while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
+	{
+		Datum		values[PG_GET_SHMEM_SIZES_COLS];
+		bool		nulls[PG_GET_SHMEM_SIZES_COLS];
+
+		/* key */
+		values[0] = CStringGetTextDatum(ent->key);
+		nulls[0] = false;
+
+		/* off */
+		values[1] = Int64GetDatum((char *) ent->location - (char *) ShmemSegHdr);
+		nulls[1] = false;
+
+		/* size */
+		values[2] = Int64GetDatum(ent->size);
+		nulls[2] = false;
+
+		/* allocated */
+		values[3] = BoolGetDatum(true);
+		nulls[3] = false;
+
+		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+	}
+
+	/* output as-of-yet unallocated memory */
+	{
+		Datum		values[PG_GET_SHMEM_SIZES_COLS];
+		bool		nulls[PG_GET_SHMEM_SIZES_COLS];
+
+		/* key, show unallocated as NULL */
+		nulls[0] = true;
+
+		/* off */
+		values[1] = Int64GetDatum(ShmemSegHdr->freeoffset);
+		nulls[1] = false;
+
+		/* size */
+		values[2] = Int64GetDatum(ShmemSegHdr->totalsize - ShmemSegHdr->freeoffset);
+		nulls[2] = false;
+
+		/* allocated */
+		values[3] = BoolGetDatum(false);
+		nulls[3] = false;
+
+		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+	}
+
+	tuplestore_donestoring(tupstore);
+
+	return (Datum) 0;
+}
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 98c183b..d018e6f 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3899,6 +3899,8 @@ DATA(insert OID = 3035 (  pg_listening_channels PGNSP PGUID 12 1 10 0 0 f f f f
 DESCR("get the channels that the current backend listens to");
 DATA(insert OID = 3036 (  pg_notify				PGNSP PGUID 12 1 0 0 0 f f f f f f v 2 0 2278 "25 25" _null_ _null_ _null_ _null_ pg_notify _null_ _null_ _null_ ));
 DESCR("send a notification event");
+DATA(insert OID = 86 (  pg_get_shmem_allocations	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{25,20,20,16}" "{o,o,o,o}" "{key, off, size, allocated}" _null_ pg_get_shmem_allocations _null_ _null_ _null_ ));
+DESCR("show shared memory allocations");
 
 /* non-persistent series generator */
 DATA(insert OID = 1066 (  generate_series PGNSP PGUID 12 1 1000 0 0 f f f f t t i 3 0 23 "23 23 23" _null_ _null_ _null_ _null_ generate_series_step_int4 _null_ _null_ _null_ ));
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 33b6dca..540015f 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -1209,4 +1209,7 @@ extern Datum pg_prepared_statement(PG_FUNCTION_ARGS);
 /* utils/mmgr/portalmem.c */
 extern Datum pg_cursor(PG_FUNCTION_ARGS);
 
+/* backend/storage/ipc/shmem.c */
+extern Datum pg_get_shmem_allocations(PG_FUNCTION_ARGS);
+
 #endif   /* BUILTINS_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 87870cf..58a125b 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -1591,6 +1591,11 @@ pg_shadow| SELECT pg_authid.rolname AS usename,
    FROM (pg_authid
      LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid))))
   WHERE pg_authid.rolcanlogin;
+pg_shmem_allocations| SELECT pg_get_shmem_allocations.key,
+    pg_get_shmem_allocations.off,
+    pg_get_shmem_allocations.size,
+    pg_get_shmem_allocations.allocated
+   FROM pg_get_shmem_allocations() pg_get_shmem_allocations(key, off, size, allocated);
 pg_stat_activity| SELECT s.datid,
     d.datname,
     s.pid,
-- 
1.8.5.rc2.dirty

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to