PostgreSQL Source Code  git master
mcxtfuncs.c File Reference
#include "postgres.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "mb/pg_wchar.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/builtins.h"
Include dependency graph for mcxtfuncs.c:

Go to the source code of this file.

Macros

#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE   1024
 
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS   9
 

Functions

static void PutMemoryContextsStatsTupleStore (Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, const char *parent, int level)
 
Datum pg_get_backend_memory_contexts (PG_FUNCTION_ARGS)
 
Datum pg_log_backend_memory_contexts (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ MEMORY_CONTEXT_IDENT_DISPLAY_SIZE

#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE   1024

Definition at line 29 of file mcxtfuncs.c.

Referenced by PutMemoryContextsStatsTupleStore().

◆ PG_GET_BACKEND_MEMORY_CONTEXTS_COLS

#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS   9

Function Documentation

◆ pg_get_backend_memory_contexts()

Datum pg_get_backend_memory_contexts ( PG_FUNCTION_ARGS  )

Definition at line 120 of file mcxtfuncs.c.

References ReturnSetInfo::allowedModes, ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, elog, ereport, errcode(), errmsg(), ERROR, get_call_result_type(), IsA, MemoryContextSwitchTo(), PutMemoryContextsStatsTupleStore(), ReturnSetInfo::returnMode, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, TopMemoryContext, tuplestore_begin_heap(), tuplestore_donestoring, TYPEFUNC_COMPOSITE, and work_mem.

121 {
122  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
123  TupleDesc tupdesc;
124  Tuplestorestate *tupstore;
125  MemoryContext per_query_ctx;
126  MemoryContext oldcontext;
127 
128  /* check to see if caller supports us returning a tuplestore */
129  if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
130  ereport(ERROR,
131  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
132  errmsg("set-valued function called in context that cannot accept a set")));
133  if (!(rsinfo->allowedModes & SFRM_Materialize))
134  ereport(ERROR,
135  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
136  errmsg("materialize mode required, but it is not allowed in this context")));
137 
138  /* Build a tuple descriptor for our result type */
139  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
140  elog(ERROR, "return type must be a row type");
141 
142  per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
143  oldcontext = MemoryContextSwitchTo(per_query_ctx);
144 
145  tupstore = tuplestore_begin_heap(true, false, work_mem);
146  rsinfo->returnMode = SFRM_Materialize;
147  rsinfo->setResult = tupstore;
148  rsinfo->setDesc = tupdesc;
149 
150  MemoryContextSwitchTo(oldcontext);
151 
152  PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
153  TopMemoryContext, NULL, 0);
154 
155  /* clean up and return the tuplestore */
156  tuplestore_donestoring(tupstore);
157 
158  return (Datum) 0;
159 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:207
#define tuplestore_donestoring(state)
Definition: tuplestore.h:60
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
static void PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, const char *parent, int level)
Definition: mcxtfuncs.c:36
#define ERROR
Definition: elog.h:46
MemoryContext TopMemoryContext
Definition: mcxt.c:48
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
uintptr_t Datum
Definition: postgres.h:411
int work_mem
Definition: globals.c:124
#define ereport(elevel,...)
Definition: elog.h:157
int allowedModes
Definition: execnodes.h:305
SetFunctionReturnMode returnMode
Definition: execnodes.h:307
MemoryContext ecxt_per_query_memory
Definition: execnodes.h:233
Tuplestorestate * setResult
Definition: execnodes.h:310
ExprContext * econtext
Definition: execnodes.h:303
TupleDesc setDesc
Definition: execnodes.h:311
int errmsg(const char *fmt,...)
Definition: elog.c:909
#define elog(elevel,...)
Definition: elog.h:232

◆ pg_log_backend_memory_contexts()

Datum pg_log_backend_memory_contexts ( PG_FUNCTION_ARGS  )

Definition at line 175 of file mcxtfuncs.c.

References PGPROC::backendId, BackendPidGetProc(), ereport, errcode(), errmsg(), ERROR, PG_GETARG_INT32, PG_RETURN_BOOL, PROCSIG_LOG_MEMORY_CONTEXT, SendProcSignal(), superuser(), and WARNING.

176 {
177  int pid = PG_GETARG_INT32(0);
178  PGPROC *proc = BackendPidGetProc(pid);
179 
180  /*
181  * BackendPidGetProc returns NULL if the pid isn't valid; but by the time
182  * we reach kill(), a process for which we get a valid proc here might
183  * have terminated on its own. There's no way to acquire a lock on an
184  * arbitrary process to prevent that. But since this mechanism is usually
185  * used to debug a backend running and consuming lots of memory, that it
186  * might end on its own first and its memory contexts are not logged is
187  * not a problem.
188  */
189  if (proc == NULL)
190  {
191  /*
192  * This is just a warning so a loop-through-resultset will not abort
193  * if one backend terminated on its own during the run.
194  */
196  (errmsg("PID %d is not a PostgreSQL server process", pid)));
197  PG_RETURN_BOOL(false);
198  }
199 
200  /* Only allow superusers to log memory contexts. */
201  if (!superuser())
202  ereport(ERROR,
203  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
204  errmsg("must be a superuser to log memory contexts")));
205 
207  {
208  /* Again, just a warning to allow loops */
210  (errmsg("could not send signal to process %d: %m", pid)));
211  PG_RETURN_BOOL(false);
212  }
213 
214  PG_RETURN_BOOL(true);
215 }
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
BackendId backendId
Definition: proc.h:153
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3067
int errcode(int sqlerrcode)
Definition: elog.c:698
bool superuser(void)
Definition: superuser.c:46
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition: procsignal.c:261
#define ERROR
Definition: elog.h:46
#define WARNING
Definition: elog.h:40
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909
Definition: proc.h:121

◆ PutMemoryContextsStatsTupleStore()

static void PutMemoryContextsStatsTupleStore ( Tuplestorestate tupstore,
TupleDesc  tupdesc,
MemoryContext  context,
const char *  parent,
int  level 
)
static

Definition at line 36 of file mcxtfuncs.c.

References AssertArg, CStringGetTextDatum, MemoryContextData::firstchild, MemoryContextData::ident, Int32GetDatum, Int64GetDatum(), MEMORY_CONTEXT_IDENT_DISPLAY_SIZE, MemoryContextIsValid, MemoryContextData::methods, MemoryContextData::name, name, MemoryContextData::nextchild, PG_GET_BACKEND_MEMORY_CONTEXTS_COLS, pg_mbcliplen(), stat, MemoryContextMethods::stats, tuplestore_putvalues(), and values.

Referenced by pg_get_backend_memory_contexts().

39 {
40 #define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 9
41 
45  MemoryContext child;
46  const char *name;
47  const char *ident;
48 
50 
51  name = context->name;
52  ident = context->ident;
53 
54  /*
55  * To be consistent with logging output, we label dynahash contexts
56  * with just the hash table name as with MemoryContextStatsPrint().
57  */
58  if (ident && strcmp(name, "dynahash") == 0)
59  {
60  name = ident;
61  ident = NULL;
62  }
63 
64  /* Examine the context itself */
65  memset(&stat, 0, sizeof(stat));
66  (*context->methods->stats) (context, NULL, (void *) &level, &stat, true);
67 
68  memset(values, 0, sizeof(values));
69  memset(nulls, 0, sizeof(nulls));
70 
71  if (name)
72  values[0] = CStringGetTextDatum(name);
73  else
74  nulls[0] = true;
75 
76  if (ident)
77  {
78  int idlen = strlen(ident);
79  char clipped_ident[MEMORY_CONTEXT_IDENT_DISPLAY_SIZE];
80 
81  /*
82  * Some identifiers such as SQL query string can be very long,
83  * truncate oversize identifiers.
84  */
86  idlen = pg_mbcliplen(ident, idlen, MEMORY_CONTEXT_IDENT_DISPLAY_SIZE - 1);
87 
88  memcpy(clipped_ident, ident, idlen);
89  clipped_ident[idlen] = '\0';
90  values[1] = CStringGetTextDatum(clipped_ident);
91  }
92  else
93  nulls[1] = true;
94 
95  if (parent)
96  values[2] = CStringGetTextDatum(parent);
97  else
98  nulls[2] = true;
99 
100  values[3] = Int32GetDatum(level);
101  values[4] = Int64GetDatum(stat.totalspace);
102  values[5] = Int64GetDatum(stat.nblocks);
103  values[6] = Int64GetDatum(stat.freespace);
104  values[7] = Int64GetDatum(stat.freechunks);
105  values[8] = Int64GetDatum(stat.totalspace - stat.freespace);
106  tuplestore_putvalues(tupstore, tupdesc, values, nulls);
107 
108  for (child = context->firstchild; child != NULL; child = child->nextchild)
109  {
110  PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
111  child, name, level + 1);
112  }
113 }
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
void(* stats)(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition: memnodes.h:68
const MemoryContextMethods * methods
Definition: memnodes.h:85
static void PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, const char *parent, int level)
Definition: mcxtfuncs.c:36
MemoryContext firstchild
Definition: memnodes.h:87
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition: mbutils.c:1026
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1697
#define AssertArg(condition)
Definition: c.h:806
const char * ident
Definition: memnodes.h:91
uintptr_t Datum
Definition: postgres.h:411
#define MemoryContextIsValid(context)
Definition: memnodes.h:104
const char * name
Definition: encode.c:515
static Datum values[MAXATTR]
Definition: bootstrap.c:166
#define Int32GetDatum(X)
Definition: postgres.h:523
#define CStringGetTextDatum(s)
Definition: builtins.h:82
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE
Definition: mcxtfuncs.c:29
const char * name
Definition: memnodes.h:90
MemoryContext nextchild
Definition: memnodes.h:89
#define stat
Definition: win32_port.h:275