On 2014-09-19 23:07:07 -0500, Michael Paquier wrote: > On Mon, Aug 18, 2014 at 1:12 PM, Robert Haas <robertmh...@gmail.com> wrote: > > On Mon, Aug 18, 2014 at 1:27 PM, Tom Lane <t...@sss.pgh.pa.us> wrote: > >> Robert Haas <robertmh...@gmail.com> writes: > >>> I thought you were printing actual pointer addresses. If you're just > >>> printing offsets relative to wherever the segment happens to be > >>> mapped, I don't care about that. > >> > >> Well, that just means that it's not an *obvious* security risk. > >> > >> I still like the idea of providing something comparable to > >> MemoryContextStats, rather than creating a SQL interface. The problem > >> with a SQL interface is you can't interrogate it unless (1) you are not > >> already inside a query and (2) the client is interactive and under your > >> control. Something you can call easily from gdb is likely to be much > >> more useful in practice. > > > > Since the shared memory segment isn't changing at runtime, I don't see > > this as being a big problem. It could possibly be an issue for > > dynamic shared memory segments, though. > Patch has been reviewed some time ago, extra ideas as well as > potential security risks discussed as well but no new version has been > sent, hence marking it as returned with feedback.
Here's a rebased version. I remember why I didn't call the column "offset" (as Michael complained about upthread), it's a keyword... Regards, Andres
>From 719f7e2493832564c58c3ab319344f31abef1653 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Tue, 6 May 2014 19:42:36 +0200 Subject: [PATCH 1/2] Associate names to created dynamic shared memory segments. This unfortunately implies an API breakage. --- src/backend/access/transam/parallel.c | 3 +- src/backend/storage/ipc/dsm.c | 61 ++++++++++++++++++++++------------- src/include/storage/dsm.h | 2 +- src/test/modules/test_shm_mq/setup.c | 2 +- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c index 0bba9a7..c1473c1 100644 --- a/src/backend/access/transam/parallel.c +++ b/src/backend/access/transam/parallel.c @@ -268,7 +268,8 @@ InitializeParallelDSM(ParallelContext *pcxt) */ segsize = shm_toc_estimate(&pcxt->estimator); if (pcxt->nworkers != 0) - pcxt->seg = dsm_create(segsize, DSM_CREATE_NULL_IF_MAXSEGMENTS); + pcxt->seg = dsm_create("parallel worker", segsize, + DSM_CREATE_NULL_IF_MAXSEGMENTS); if (pcxt->seg != NULL) pcxt->toc = shm_toc_create(PARALLEL_MAGIC, dsm_segment_address(pcxt->seg), diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index 573c54d..7166328 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -80,8 +80,10 @@ struct dsm_segment /* Shared-memory state for a dynamic shared memory segment. */ typedef struct dsm_control_item { - dsm_handle handle; + dsm_handle handle; /* segment identifier */ uint32 refcnt; /* 2+ = active, 1 = moribund, 0 = gone */ + Size size; /* current size */ + char name[SHMEM_INDEX_KEYSIZE]; /* informational name */ } dsm_control_item; /* Layout of the dynamic shared memory control segment. */ @@ -454,15 +456,18 @@ dsm_set_control_handle(dsm_handle h) * Create a new dynamic shared memory segment. */ dsm_segment * -dsm_create(Size size, int flags) +dsm_create(const char *name, Size size, int flags) { dsm_segment *seg; - uint32 i; - uint32 nitems; + dsm_control_item *item; + uint32 slot; /* Unsafe in postmaster (and pointless in a stand-alone backend). */ Assert(IsUnderPostmaster); + Assert(name != NULL && strlen(name) > 0 && + strlen(name) < SHMEM_INDEX_KEYSIZE - 1); + if (!dsm_init_done) dsm_backend_startup(); @@ -482,23 +487,18 @@ dsm_create(Size size, int flags) /* Lock the control segment so we can register the new segment. */ LWLockAcquire(DynamicSharedMemoryControlLock, LW_EXCLUSIVE); - /* Search the control segment for an unused slot. */ - nitems = dsm_control->nitems; - for (i = 0; i < nitems; ++i) + /* + * Search the control segment for an unused slot that's previously been + * used. If we don't find one initialize a new one if there's still space. + */ + for (slot = 0; slot < dsm_control->nitems; ++slot) { - if (dsm_control->item[i].refcnt == 0) - { - dsm_control->item[i].handle = seg->handle; - /* refcnt of 1 triggers destruction, so start at 2 */ - dsm_control->item[i].refcnt = 2; - seg->control_slot = i; - LWLockRelease(DynamicSharedMemoryControlLock); - return seg; - } + if (dsm_control->item[slot].refcnt == 0) + break; } - /* Verify that we can support an additional mapping. */ - if (nitems >= dsm_control->maxitems) + /* Verify that we can support the mapping. */ + if (slot >= dsm_control->maxitems) { if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0) { @@ -516,12 +516,23 @@ dsm_create(Size size, int flags) errmsg("too many dynamic shared memory segments"))); } - /* Enter the handle into a new array slot. */ - dsm_control->item[nitems].handle = seg->handle; + item = &dsm_control->item[slot]; + item->handle = seg->handle; /* refcnt of 1 triggers destruction, so start at 2 */ - dsm_control->item[nitems].refcnt = 2; - seg->control_slot = nitems; - dsm_control->nitems++; + item->refcnt = 2; + item->size = size; + strncpy(item->name, name, SHMEM_INDEX_KEYSIZE); + item->name[SHMEM_INDEX_KEYSIZE - 1] = 0; + + seg->control_slot = slot; + + /* + * Increase number of initilized slots if we didn't reuse a previously + * used one. + */ + if (slot >= dsm_control->nitems) + dsm_control->nitems++; + LWLockRelease(DynamicSharedMemoryControlLock); return seg; @@ -674,6 +685,10 @@ dsm_resize(dsm_segment *seg, Size size) Assert(seg->control_slot != INVALID_CONTROL_SLOT); dsm_impl_op(DSM_OP_RESIZE, seg->handle, size, &seg->impl_private, &seg->mapped_address, &seg->mapped_size, ERROR); + + /* persist the changed size */ + dsm_control->item[seg->control_slot].size = size; + return seg->mapped_address; } diff --git a/src/include/storage/dsm.h b/src/include/storage/dsm.h index 86ede7a..278a1ac 100644 --- a/src/include/storage/dsm.h +++ b/src/include/storage/dsm.h @@ -31,7 +31,7 @@ extern void dsm_set_control_handle(dsm_handle h); #endif /* Functions that create, update, or remove mappings. */ -extern dsm_segment *dsm_create(Size size, int flags); +extern dsm_segment *dsm_create(const char *name, Size size, int flags); extern dsm_segment *dsm_attach(dsm_handle h); extern void *dsm_resize(dsm_segment *seg, Size size); extern void *dsm_remap(dsm_segment *seg); diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c index 5bd2820..13ad00c 100644 --- a/src/test/modules/test_shm_mq/setup.c +++ b/src/test/modules/test_shm_mq/setup.c @@ -125,7 +125,7 @@ setup_dynamic_shared_memory(int64 queue_size, int nworkers, segsize = shm_toc_estimate(&e); /* Create the shared memory segment and establish a table of contents. */ - seg = dsm_create(shm_toc_estimate(&e), 0); + seg = dsm_create("test_shm_mq", shm_toc_estimate(&e), 0); toc = shm_toc_create(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg), segsize); -- 2.7.0.229.g701fa7f
>From e5ff0836922f988a76b73aa95e70debfb16c4d82 Mon Sep 17 00:00:00 2001 From: Andres Freund <and...@anarazel.de> Date: Sun, 4 May 2014 13:37:20 +0200 Subject: [PATCH 2/2] Add views to see shared memory allocations. Add the pg_shmem_allocations and pg_dynamic_shmem_allocations views. These are useful to see what memory is being used for. --- doc/src/sgml/catalogs.sgml | 135 +++++++++++++++++++++++++++++++++++ doc/src/sgml/xfunc.sgml | 2 +- src/backend/catalog/system_views.sql | 6 ++ src/backend/storage/ipc/dsm.c | 80 +++++++++++++++++++++ src/backend/storage/ipc/shmem.c | 113 +++++++++++++++++++++++++++++ src/include/catalog/pg_proc.h | 4 ++ src/include/utils/builtins.h | 5 ++ src/test/regress/expected/rules.out | 9 +++ 8 files changed, 353 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index eac6671..e1ca97d 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -7835,6 +7835,73 @@ </sect1> + <sect1 id="view-pg-dynamic-shmem-allocations"> + <title><structname>pg_dynamic_shmem_allocations</structname></title> + + <indexterm zone="view-pg-dynamic-shmem-allocations"> + <primary>pg_dynamic_shmem_allocations</primary> + </indexterm> + + <para> + The <structname>pg_dynamic_shmem_allocations</structname> view shows + information about the currently existing dynamic shared memory segments. + </para> + + <para> + Note that this view does not include shared memory allocated at server + startup. That is shown in + the <link linkend="view-pg-shmem-allocations"><structname>pg_shmem_allocations</structname></link> + view. + </para> + + <table> + <title><structname>pg_dynamic_shmem_allocations</structname> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>handle</structfield></entry> + <entry><type>int64</type></entry> + <entry>The identifier used to refer to this specific segment.</entry> + </row> + + <row> + <entry><structfield>name</structfield></entry> + <entry><type>text</type></entry> + <entry>Informational name for this segment.</entry> + </row> + + <row> + <entry><structfield>size</structfield></entry> + <entry><type>bigint</type></entry> + <entry>Size of the segment.</entry> + </row> + + <row> + <entry><structfield>refcnt</structfield></entry> + <entry><type>bigint</type></entry> + <entry> + Number of backends attached to this segment (1 signals a moribund + entry, 2 signals one user, ...). + </entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + The <structname>pg_shmem_allocations</structname> view is read only. + </para> + </sect1> + <sect1 id="view-pg-group"> <title><structname>pg_group</structname></title> @@ -9467,6 +9534,74 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx </sect1> + <sect1 id="view-pg-shmem-allocations"> + <title><structname>pg_shmem_allocations</structname></title> + + <indexterm zone="view-pg-shmem-allocations"> + <primary>pg_shmem_allocations</primary> + </indexterm> + + <para> + The <structname>pg_shmem_allocations</structname> view shows what the + server's shared memory is being used for. That includes memory allocated by + <productname>postgres</> itself and memory used by extensions using the + mechanisms detailed in <xref linkend="xfunc-shared-addin">. + </para> + + <para> + Note that this view does not include memory allocated using the dynamic + shared memory infrastructure. That is shown in + the <link linkend="view-pg-dynamic-shmem-allocations"><structname>pg_dynamic_shmem_allocations</structname></link> + view. + </para> + + <table> + <title><structname>pg_shmem_allocations</structname> Columns</title> + + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>name</structfield></entry> + <entry><type>text</type></entry> + <entry>The name of the shared memory allocation. NULL for unused memory + and <anonymous> for anonymous allocations.</entry> + </row> + + <row> + <entry><structfield>off</structfield></entry> + <entry><type>bigint</type></entry> + <entry>The offset at which the allocation starts. NULL for anonymous + allocations.</entry> + </row> + + <row> + <entry><structfield>size</structfield></entry> + <entry><type>bigint</type></entry> + <entry>Size of the allocation</entry> + </row> + </tbody> + </tgroup> + </table> + + <para> + Anonymous allocations are allocations that have been made + with <literal>ShmemAlloc()</> and not <literal>ShmemInitStruct()</literal>. + </para> + + <para> + The <structname>pg_shmem_allocations</structname> view is read only. + </para> + + </sect1> + <sect1 id="view-pg-stats"> <title><structname>pg_stats</structname></title> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index d8d2e9e..b59512f 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3318,7 +3318,7 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray </para> </sect2> - <sect2> + <sect2 id="xfunc-shared-addin"> <title>Shared Memory and LWLocks</title> <para> diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 272c02f..8f55801 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -439,6 +439,12 @@ CREATE VIEW pg_config AS REVOKE ALL on pg_config FROM PUBLIC; REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC; +CREATE VIEW pg_shmem_allocations AS + SELECT * FROM pg_get_shmem_allocations(); + +CREATE VIEW pg_dynamic_shmem_allocations AS + SELECT * FROM pg_get_dynamic_shmem_allocations(); + -- Statistics views CREATE VIEW pg_stat_all_tables AS diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c index 7166328..ce8d1e9 100644 --- a/src/backend/storage/ipc/dsm.c +++ b/src/backend/storage/ipc/dsm.c @@ -34,12 +34,15 @@ #endif #include <sys/stat.h> +#include "fmgr.h" +#include "funcapi.h" #include "lib/ilist.h" #include "miscadmin.h" #include "storage/dsm.h" #include "storage/ipc.h" #include "storage/lwlock.h" #include "storage/pg_shmem.h" +#include "utils/builtins.h" #include "utils/guc.h" #include "utils/memutils.h" #include "utils/resowner_private.h" @@ -1057,3 +1060,80 @@ dsm_control_bytes_needed(uint32 nitems) return offsetof(dsm_control_header, item) +sizeof(dsm_control_item) * (uint64) nitems; } + +/* SQL SRF showing allocated shared memory */ +Datum +pg_get_dynamic_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; + int i; + + /* 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); + + LWLockAcquire(DynamicSharedMemoryControlLock, LW_SHARED); + + for (i = 0; i < dsm_control->nitems; ++i) + { + dsm_control_item *item; + Datum values[PG_GET_SHMEM_SIZES_COLS]; + bool nulls[PG_GET_SHMEM_SIZES_COLS]; + + /* don't look at unused or about to be destroyed items */ + if (dsm_control->item[i].refcnt < 2) + continue; + + item = &dsm_control->item[i]; + + /* handle */ + values[0] = Int64GetDatum(item->handle); + nulls[0] = false; + + /* name */ + values[1] = CStringGetTextDatum(item->name); + nulls[1] = false; + + /* size */ + values[2] = Int64GetDatum(item->size); + nulls[2] = false; + + /* refcnt */ + values[3] = Int64GetDatum(item->refcnt - 2); + nulls[3] = false; + + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + } + LWLockRelease(DynamicSharedMemoryControlLock); + + tuplestore_donestoring(tupstore); + + return (Datum) 0; +} diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 1efe020..f21bdfc 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 */ @@ -471,3 +474,113 @@ 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 3 + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; + TupleDesc tupdesc; + Tuplestorestate *tupstore; + MemoryContext per_query_ctx; + MemoryContext oldcontext; + HASH_SEQ_STATUS hstat; + ShmemIndexEnt *ent; + Size named_allocated = 0; + + /* 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); + + LWLockAcquire(ShmemIndexLock, LW_SHARED); + + 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; + named_allocated += ent->size; + + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + } + + /* output shared memory allocated but not counted via the shmem index */ + { + Datum values[PG_GET_SHMEM_SIZES_COLS]; + bool nulls[PG_GET_SHMEM_SIZES_COLS]; + + /* key */ + values[0] = CStringGetTextDatum("<anonymous>"); + nulls[0] = false; + + /* off */ + nulls[1] = true; + + /* size */ + values[2] = Int64GetDatum(ShmemSegHdr->freeoffset - named_allocated); + nulls[2] = false; + + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + } + + /* output as-of-yet unused shared 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; + + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + } + + LWLockRelease(ShmemIndexLock); + + tuplestore_donestoring(tupstore); + + return (Datum) 0; +} diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 021ba50..465342b 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -4054,6 +4054,10 @@ DATA(insert OID = 3036 ( pg_notify PGNSP PGUID 12 1 0 0 0 f f f f f f v r 2 DESCR("send a notification event"); DATA(insert OID = 3296 ( pg_notification_queue_usage PGNSP PGUID 12 1 0 0 0 f f f f t f v s 0 0 701 "" _null_ _null_ _null_ _null_ _null_ pg_notification_queue_usage _null_ _null_ _null_ )); DESCR("get the fraction of the asynchronous notification queue currently in use"); +DATA(insert OID = 441 ( pg_get_shmem_allocations PGNSP PGUID 12 1 10 0 0 f f f f f t s s 0 0 2249 "" "{25,20,20}" "{o,o,o}" "{key, off, size}" _null_ _null_ pg_get_shmem_allocations _null_ _null_ _null_ )); +DESCR("show shared memory allocations"); +DATA(insert OID = 448 ( pg_get_dynamic_shmem_allocations PGNSP PGUID 12 1 10 0 0 f f f f f t s s 0 0 2249 "" "{20,25,20,20}" "{o,o,o,o}" "{handle, name, size, refcnt}" _null_ _null_ pg_get_dynamic_shmem_allocations _null_ _null_ _null_ )); +DESCR("show dynamic 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 s 3 0 23 "23 23 23" _null_ _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 01976a1..30eedd5 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -1322,4 +1322,9 @@ 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); +/* backend/storage/ipc/dsm.c */ +extern Datum pg_get_dynamic_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 5521a16..ae985a7 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1323,6 +1323,11 @@ pg_cursors| SELECT c.name, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time); +pg_dynamic_shmem_allocations| SELECT pg_get_dynamic_shmem_allocations.handle, + pg_get_dynamic_shmem_allocations.name, + pg_get_dynamic_shmem_allocations.size, + pg_get_dynamic_shmem_allocations.refcnt + FROM pg_get_dynamic_shmem_allocations() pg_get_dynamic_shmem_allocations(handle, name, size, refcnt); pg_file_settings| SELECT a.sourcefile, a.sourceline, a.seqno, @@ -1645,6 +1650,10 @@ 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 + FROM pg_get_shmem_allocations() pg_get_shmem_allocations(key, off, size); pg_stat_activity| SELECT s.datid, d.datname, s.pid, -- 2.7.0.229.g701fa7f
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers