Move codes for pg_backend_memory_contexts from mmgr/mcxt.c to adt/mcxtfuncs.c.

Previously the codes for pg_backend_memory_contexts were in
src/backend/utils/mmgr/mcxt.c. This commit moves them to
src/backend/utils/adt/mcxtfuncs.c so that mcxt.c basically includes
only the low-level interface for memory contexts.

Author: Atsushi Torikoshi
Reviewed-by: Michael Paquier, Fujii Masao
Discussion: https://postgr.es/m/20200819135545.GC19121@paquier.xyz
This commit is contained in:
Fujii Masao 2020-08-26 10:51:31 +09:00
parent 29dd6d8bc6
commit 50db5964ee
3 changed files with 158 additions and 137 deletions

View File

@ -57,6 +57,7 @@ OBJS = \
lockfuncs.o \
mac.o \
mac8.o \
mcxtfuncs.o \
misc.o \
name.o \
network.o \

View File

@ -0,0 +1,157 @@
/*-------------------------------------------------------------------------
*
* mcxtfuncs.c
* Functions to show backend memory context.
*
* Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/backend/utils/adt/mcxtfuncs.c
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
/* ----------
* The max bytes for showing identifiers of MemoryContext.
* ----------
*/
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE 1024
/*
* PutMemoryContextsStatsTupleStore
* One recursion level for pg_get_backend_memory_contexts.
*/
static void
PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore,
TupleDesc tupdesc, MemoryContext context,
const char *parent, int level)
{
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 9
Datum values[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
bool nulls[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
MemoryContextCounters stat;
MemoryContext child;
const char *name;
const char *ident;
AssertArg(MemoryContextIsValid(context));
name = context->name;
ident = context->ident;
/*
* To be consistent with logging output, we label dynahash contexts
* with just the hash table name as with MemoryContextStatsPrint().
*/
if (ident && strcmp(name, "dynahash") == 0)
{
name = ident;
ident = NULL;
}
/* Examine the context itself */
memset(&stat, 0, sizeof(stat));
(*context->methods->stats) (context, NULL, (void *) &level, &stat);
memset(values, 0, sizeof(values));
memset(nulls, 0, sizeof(nulls));
if (name)
values[0] = CStringGetTextDatum(name);
else
nulls[0] = true;
if (ident)
{
int idlen = strlen(ident);
char clipped_ident[MEMORY_CONTEXT_IDENT_DISPLAY_SIZE];
/*
* Some identifiers such as SQL query string can be very long,
* truncate oversize identifiers.
*/
if (idlen >= MEMORY_CONTEXT_IDENT_DISPLAY_SIZE)
idlen = pg_mbcliplen(ident, idlen, MEMORY_CONTEXT_IDENT_DISPLAY_SIZE - 1);
memcpy(clipped_ident, ident, idlen);
clipped_ident[idlen] = '\0';
values[1] = CStringGetTextDatum(clipped_ident);
}
else
nulls[1] = true;
if (parent)
values[2] = CStringGetTextDatum(parent);
else
nulls[2] = true;
values[3] = Int32GetDatum(level);
values[4] = Int64GetDatum(stat.totalspace);
values[5] = Int64GetDatum(stat.nblocks);
values[6] = Int64GetDatum(stat.freespace);
values[7] = Int64GetDatum(stat.freechunks);
values[8] = Int64GetDatum(stat.totalspace - stat.freespace);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
for (child = context->firstchild; child != NULL; child = child->nextchild)
{
PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
child, name, level + 1);
}
}
/*
* pg_get_backend_memory_contexts
* SQL SRF showing backend memory context.
*/
Datum
pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc tupdesc;
Tuplestorestate *tupstore;
MemoryContext per_query_ctx;
MemoryContext oldcontext;
/* 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);
PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
TopMemoryContext, NULL, 0);
/* clean up and return the tuplestore */
tuplestore_donestoring(tupstore);
return (Datum) 0;
}

View File

@ -21,10 +21,8 @@
#include "postgres.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/memdebug.h"
#include "utils/memutils.h"
@ -69,11 +67,6 @@ static void MemoryContextStatsPrint(MemoryContext context, void *passthru,
#define AssertNotInCriticalSection(context) \
Assert(CritSectionCount == 0 || (context)->allowInCritSection)
/* ----------
* The max bytes for showing identifiers of MemoryContext.
* ----------
*/
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE 1024
/*****************************************************************************
* EXPORTED ROUTINES *
@ -1228,133 +1221,3 @@ pchomp(const char *in)
n--;
return pnstrdup(in, n);
}
/*
* PutMemoryContextsStatsTupleStore
* One recursion level for pg_get_backend_memory_contexts.
*/
static void
PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore,
TupleDesc tupdesc, MemoryContext context,
const char *parent, int level)
{
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 9
Datum values[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
bool nulls[PG_GET_BACKEND_MEMORY_CONTEXTS_COLS];
MemoryContextCounters stat;
MemoryContext child;
const char *name;
const char *ident;
AssertArg(MemoryContextIsValid(context));
name = context->name;
ident = context->ident;
/*
* To be consistent with logging output, we label dynahash contexts
* with just the hash table name as with MemoryContextStatsPrint().
*/
if (ident && strcmp(name, "dynahash") == 0)
{
name = ident;
ident = NULL;
}
/* Examine the context itself */
memset(&stat, 0, sizeof(stat));
(*context->methods->stats) (context, NULL, (void *) &level, &stat);
memset(values, 0, sizeof(values));
memset(nulls, 0, sizeof(nulls));
if (name)
values[0] = CStringGetTextDatum(name);
else
nulls[0] = true;
if (ident)
{
int idlen = strlen(ident);
char clipped_ident[MEMORY_CONTEXT_IDENT_DISPLAY_SIZE];
/*
* Some identifiers such as SQL query string can be very long,
* truncate oversize identifiers.
*/
if (idlen >= MEMORY_CONTEXT_IDENT_DISPLAY_SIZE)
idlen = pg_mbcliplen(ident, idlen, MEMORY_CONTEXT_IDENT_DISPLAY_SIZE - 1);
memcpy(clipped_ident, ident, idlen);
clipped_ident[idlen] = '\0';
values[1] = CStringGetTextDatum(clipped_ident);
}
else
nulls[1] = true;
if (parent)
values[2] = CStringGetTextDatum(parent);
else
nulls[2] = true;
values[3] = Int32GetDatum(level);
values[4] = Int64GetDatum(stat.totalspace);
values[5] = Int64GetDatum(stat.nblocks);
values[6] = Int64GetDatum(stat.freespace);
values[7] = Int64GetDatum(stat.freechunks);
values[8] = Int64GetDatum(stat.totalspace - stat.freespace);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
for (child = context->firstchild; child != NULL; child = child->nextchild)
{
PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
child, name, level + 1);
}
}
/*
* pg_get_backend_memory_contexts
* SQL SRF showing backend memory context.
*/
Datum
pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
TupleDesc tupdesc;
Tuplestorestate *tupstore;
MemoryContext per_query_ctx;
MemoryContext oldcontext;
/* 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);
PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
TopMemoryContext, NULL, 0);
/* clean up and return the tuplestore */
tuplestore_donestoring(tupstore);
return (Datum) 0;
}