PostgreSQL Source Code git master
Loading...
Searching...
No Matches
mcxtfuncs.c File Reference
#include "postgres.h"
#include "catalog/pg_type_d.h"
#include "funcapi.h"
#include "mb/pg_wchar.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/procsignal.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/tuplestore.h"
Include dependency graph for mcxtfuncs.c:

Go to the source code of this file.

Data Structures

struct  MemoryContextId
 

Macros

#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE   1024
 
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS   10
 

Typedefs

typedef struct MemoryContextId MemoryContextId
 

Functions

static Datum int_list_to_array (const List *list)
 
static void PutMemoryContextsStatsTupleStore (Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, HTAB *context_id_lookup)
 
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 33 of file mcxtfuncs.c.

◆ PG_GET_BACKEND_MEMORY_CONTEXTS_COLS

#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS   10

Typedef Documentation

◆ MemoryContextId

Function Documentation

◆ int_list_to_array()

static Datum int_list_to_array ( const List list)
static

Definition at line 51 of file mcxtfuncs.c.

52{
54 int length;
56
57 length = list_length(list);
59
60 foreach_int(i, list)
62
64
66}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
#define palloc_array(type, count)
Definition fe_memutils.h:76
int i
Definition isn.c:77
static int list_length(const List *l)
Definition pg_list.h:152
#define foreach_current_index(var_or_cell)
Definition pg_list.h:435
#define foreach_int(var, lst)
Definition pg_list.h:502
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
uint64_t Datum
Definition postgres.h:70
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static int fb(int x)

References construct_array_builtin(), fb(), foreach_current_index, foreach_int, i, Int32GetDatum(), list_length(), palloc_array, and PointerGetDatum().

Referenced by PutMemoryContextsStatsTupleStore().

◆ pg_get_backend_memory_contexts()

Datum pg_get_backend_memory_contexts ( PG_FUNCTION_ARGS  )

Definition at line 186 of file mcxtfuncs.c.

187{
188 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
189 int context_id;
190 List *contexts;
191 HASHCTL ctl;
193
194 ctl.keysize = sizeof(MemoryContext);
195 ctl.entrysize = sizeof(MemoryContextId);
197
198 context_id_lookup = hash_create("pg_get_backend_memory_contexts",
199 256,
200 &ctl,
202
203 InitMaterializedSRF(fcinfo, 0);
204
205 /*
206 * Here we use a non-recursive algorithm to visit all MemoryContexts
207 * starting with TopMemoryContext. The reason we avoid using a recursive
208 * algorithm is because we want to assign the context_id breadth-first.
209 * I.e. all contexts at level 1 are assigned IDs before contexts at level
210 * 2. Because contexts closer to TopMemoryContext are less likely to
211 * change, this makes the assigned context_id more stable. Otherwise, if
212 * the first child of TopMemoryContext obtained an additional grandchild,
213 * the context_id for the second child of TopMemoryContext would change.
214 */
216
217 /* TopMemoryContext will always have a context_id of 1 */
218 context_id = 1;
219
221 {
222 MemoryContextId *entry;
223 bool found;
224
225 /*
226 * Record the context_id that we've assigned to each MemoryContext.
227 * PutMemoryContextsStatsTupleStore needs this to populate the "path"
228 * column with the parent context_ids.
229 */
231 HASH_ENTER, &found);
232 entry->context_id = context_id++;
233 Assert(!found);
234
236 rsinfo->setDesc,
237 cur,
239
240 /*
241 * Append all children onto the contexts list so they're processed by
242 * subsequent iterations.
243 */
244 for (MemoryContext c = cur->firstchild; c != NULL; c = c->nextchild)
246 }
247
249
250 return (Datum) 0;
251}
#define Assert(condition)
Definition c.h:943
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition dynahash.c:938
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:354
void hash_destroy(HTAB *hashp)
Definition dynahash.c:851
struct cursor * cur
Definition ecpg.c:29
void InitMaterializedSRF(FunctionCallInfo fcinfo, uint32 flags)
Definition funcapi.c:76
@ HASH_ENTER
Definition hsearch.h:112
#define HASH_CONTEXT
Definition hsearch.h:100
#define HASH_ELEM
Definition hsearch.h:93
#define HASH_BLOBS
Definition hsearch.h:95
List * lappend(List *list, void *datum)
Definition list.c:339
MemoryContext TopMemoryContext
Definition mcxt.c:166
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
static void PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, HTAB *context_id_lookup)
Definition mcxtfuncs.c:73
struct MemoryContextData * MemoryContext
Definition palloc.h:36
#define list_make1(x1)
Definition pg_list.h:244
#define foreach_ptr(type, var, lst)
Definition pg_list.h:501
char * c
tree ctl
Definition radixtree.h:1838
Size keysize
Definition dynahash.c:236
Definition pg_list.h:54

References Assert, MemoryContextId::context_id, ctl, cur, CurrentMemoryContext, fb(), foreach_ptr, HASH_BLOBS, HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, HASH_ENTER, hash_search(), InitMaterializedSRF(), HTAB::keysize, lappend(), list_make1, PutMemoryContextsStatsTupleStore(), and TopMemoryContext.

◆ pg_log_backend_memory_contexts()

Datum pg_log_backend_memory_contexts ( PG_FUNCTION_ARGS  )

Definition at line 267 of file mcxtfuncs.c.

268{
269 int pid = PG_GETARG_INT32(0);
270 PGPROC *proc;
271 ProcNumber procNumber = INVALID_PROC_NUMBER;
272
273 /*
274 * See if the process with given pid is a backend or an auxiliary process.
275 */
276 proc = BackendPidGetProc(pid);
277 if (proc == NULL)
278 proc = AuxiliaryPidGetProc(pid);
279
280 /*
281 * BackendPidGetProc() and AuxiliaryPidGetProc() return NULL if the pid
282 * isn't valid; but by the time we reach kill(), a process for which we
283 * get a valid proc here might have terminated on its own. There's no way
284 * to acquire a lock on an arbitrary process to prevent that. But since
285 * this mechanism is usually used to debug a backend or an auxiliary
286 * process running and consuming lots of memory, that it might end on its
287 * own first and its memory contexts are not logged is not a problem.
288 */
289 if (proc == NULL)
290 {
291 /*
292 * This is just a warning so a loop-through-resultset will not abort
293 * if one backend terminated on its own during the run.
294 */
296 (errmsg("PID %d is not a PostgreSQL server process", pid)));
297 PG_RETURN_BOOL(false);
298 }
299
300 procNumber = GetNumberFromPGProc(proc);
301 if (SendProcSignal(pid, PROCSIG_LOG_MEMORY_CONTEXT, procNumber) < 0)
302 {
303 /* Again, just a warning to allow loops */
305 (errmsg("could not send signal to process %d: %m", pid)));
306 PG_RETURN_BOOL(false);
307 }
308
309 PG_RETURN_BOOL(true);
310}
#define WARNING
Definition elog.h:36
#define ereport(elevel,...)
Definition elog.h:151
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_RETURN_BOOL(x)
Definition fmgr.h:360
static char * errmsg
#define GetNumberFromPGProc(proc)
Definition proc.h:504
PGPROC * BackendPidGetProc(int pid)
Definition procarray.c:3156
#define INVALID_PROC_NUMBER
Definition procnumber.h:26
int ProcNumber
Definition procnumber.h:24
int SendProcSignal(pid_t pid, ProcSignalReason reason, ProcNumber procNumber)
Definition procsignal.c:287
@ PROCSIG_LOG_MEMORY_CONTEXT
Definition procsignal.h:37
PGPROC * AuxiliaryPidGetProc(int pid)
Definition proc.c:1086
Definition proc.h:178

References AuxiliaryPidGetProc(), BackendPidGetProc(), ereport, errmsg, fb(), GetNumberFromPGProc, INVALID_PROC_NUMBER, PG_GETARG_INT32, PG_RETURN_BOOL, PROCSIG_LOG_MEMORY_CONTEXT, SendProcSignal(), and WARNING.

◆ PutMemoryContextsStatsTupleStore()

static void PutMemoryContextsStatsTupleStore ( Tuplestorestate tupstore,
TupleDesc  tupdesc,
MemoryContext  context,
HTAB context_id_lookup 
)
static

Definition at line 73 of file mcxtfuncs.c.

76{
77#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 10
78
82 List *path = NIL;
83 const char *name;
84 const char *ident;
85 const char *type;
86
88
89 /*
90 * Figure out the transient context_id of this context and each of its
91 * ancestors.
92 */
93 for (MemoryContext cur = context; cur != NULL; cur = cur->parent)
94 {
95 MemoryContextId *entry;
96 bool found;
97
98 entry = hash_search(context_id_lookup, &cur, HASH_FIND, &found);
99
100 if (!found)
101 elog(ERROR, "hash table corrupted");
102 path = lcons_int(entry->context_id, path);
103 }
104
105 /* Examine the context itself */
106 memset(&stat, 0, sizeof(stat));
107 (*context->methods->stats) (context, NULL, NULL, &stat, true);
108
109 memset(values, 0, sizeof(values));
110 memset(nulls, 0, sizeof(nulls));
111
112 name = context->name;
113 ident = context->ident;
114
115 /*
116 * To be consistent with logging output, we label dynahash contexts with
117 * just the hash table name as with MemoryContextStatsPrint().
118 */
119 if (ident && strcmp(name, "dynahash") == 0)
120 {
121 name = ident;
122 ident = NULL;
123 }
124
125 if (name)
127 else
128 nulls[0] = true;
129
130 if (ident)
131 {
132 int idlen = strlen(ident);
134
135 /*
136 * Some identifiers such as SQL query string can be very long,
137 * truncate oversize identifiers.
138 */
141
143 clipped_ident[idlen] = '\0';
145 }
146 else
147 nulls[1] = true;
148
149 switch (context->type)
150 {
152 type = "AllocSet";
153 break;
155 type = "Generation";
156 break;
157 case T_SlabContext:
158 type = "Slab";
159 break;
160 case T_BumpContext:
161 type = "Bump";
162 break;
163 default:
164 type = "???";
165 break;
166 }
167
169 values[3] = Int32GetDatum(list_length(path)); /* level */
170 values[4] = int_list_to_array(path);
171 values[5] = Int64GetDatum(stat.totalspace);
172 values[6] = Int64GetDatum(stat.nblocks);
173 values[7] = Int64GetDatum(stat.freespace);
174 values[8] = Int64GetDatum(stat.freechunks);
175 values[9] = Int64GetDatum(stat.totalspace - stat.freespace);
176
177 tuplestore_putvalues(tupstore, tupdesc, values, nulls);
178 list_free(path);
179}
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define ERROR
Definition elog.h:39
#define elog(elevel,...)
Definition elog.h:227
@ HASH_FIND
Definition hsearch.h:111
#define ident
List * lcons_int(int datum, List *list)
Definition list.c:513
void list_free(List *list)
Definition list.c:1546
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition mbutils.c:1211
static Datum int_list_to_array(const List *list)
Definition mcxtfuncs.c:51
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE
Definition mcxtfuncs.c:33
#define MemoryContextIsValid(context)
Definition memnodes.h:145
#define NIL
Definition pg_list.h:68
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
const char * ident
Definition memnodes.h:132
const MemoryContextMethods * methods
Definition memnodes.h:126
const char * name
Definition memnodes.h:131
void(* stats)(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition memnodes.h:102
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
const char * type
const char * name
#define stat
Definition win32_port.h:74

References Assert, MemoryContextId::context_id, CStringGetTextDatum, cur, elog, ERROR, fb(), HASH_FIND, hash_search(), MemoryContextData::ident, ident, Int32GetDatum(), Int64GetDatum(), int_list_to_array(), lcons_int(), list_free(), list_length(), MEMORY_CONTEXT_IDENT_DISPLAY_SIZE, MemoryContextIsValid, MemoryContextData::methods, name, MemoryContextData::name, NIL, PG_GET_BACKEND_MEMORY_CONTEXTS_COLS, pg_mbcliplen(), stat, MemoryContextMethods::stats, tuplestore_putvalues(), type, and values.

Referenced by pg_get_backend_memory_contexts().