PostgreSQL Source Code
git master
mcxtfuncs.c
Go to the documentation of this file.
1
/*-------------------------------------------------------------------------
2
*
3
* mcxtfuncs.c
4
* Functions to show backend memory context.
5
*
6
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
8
*
9
*
10
* IDENTIFICATION
11
* src/backend/utils/adt/mcxtfuncs.c
12
*
13
*-------------------------------------------------------------------------
14
*/
15
16
#include "
postgres.h
"
17
18
#include "
funcapi.h
"
19
#include "
miscadmin.h
"
20
#include "
mb/pg_wchar.h
"
21
#include "
storage/proc.h
"
22
#include "
storage/procarray.h
"
23
#include "
utils/builtins.h
"
24
25
/* ----------
26
* The max bytes for showing identifiers of MemoryContext.
27
* ----------
28
*/
29
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE 1024
30
31
/*
32
* PutMemoryContextsStatsTupleStore
33
* One recursion level for pg_get_backend_memory_contexts.
34
*/
35
static
void
36
PutMemoryContextsStatsTupleStore
(
Tuplestorestate
*tupstore,
37
TupleDesc
tupdesc,
MemoryContext
context,
38
const
char
*parent,
int
level)
39
{
40
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS 9
41
42
Datum
values
[
PG_GET_BACKEND_MEMORY_CONTEXTS_COLS
];
43
bool
nulls[
PG_GET_BACKEND_MEMORY_CONTEXTS_COLS
];
44
MemoryContextCounters
stat
;
45
MemoryContext
child;
46
const
char
*
name
;
47
const
char
*
ident
;
48
49
Assert
(
MemoryContextIsValid
(context));
50
51
name
= context->
name
;
52
ident
= context->
ident
;
53
54
/*
55
* To be consistent with logging output, we label dynahash contexts with
56
* 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
*/
85
if
(idlen >=
MEMORY_CONTEXT_IDENT_DISPLAY_SIZE
)
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
}
114
115
/*
116
* pg_get_backend_memory_contexts
117
* SQL SRF showing backend memory context.
118
*/
119
Datum
120
pg_get_backend_memory_contexts
(
PG_FUNCTION_ARGS
)
121
{
122
ReturnSetInfo
*rsinfo = (
ReturnSetInfo
*) fcinfo->resultinfo;
123
124
InitMaterializedSRF
(fcinfo, 0);
125
PutMemoryContextsStatsTupleStore
(rsinfo->
setResult
, rsinfo->
setDesc
,
126
TopMemoryContext
, NULL, 0);
127
128
return
(
Datum
) 0;
129
}
130
131
/*
132
* pg_log_backend_memory_contexts
133
* Signal a backend or an auxiliary process to log its memory contexts.
134
*
135
* By default, only superusers are allowed to signal to log the memory
136
* contexts because allowing any users to issue this request at an unbounded
137
* rate would cause lots of log messages and which can lead to denial of
138
* service. Additional roles can be permitted with GRANT.
139
*
140
* On receipt of this signal, a backend or an auxiliary process sets the flag
141
* in the signal handler, which causes the next CHECK_FOR_INTERRUPTS()
142
* or process-specific interrupt handler to log the memory contexts.
143
*/
144
Datum
145
pg_log_backend_memory_contexts
(
PG_FUNCTION_ARGS
)
146
{
147
int
pid =
PG_GETARG_INT32
(0);
148
PGPROC
*proc;
149
BackendId
backendId =
InvalidBackendId
;
150
151
proc =
BackendPidGetProc
(pid);
152
153
/*
154
* See if the process with given pid is a backend or an auxiliary process.
155
*
156
* If the given process is a backend, use its backend id in
157
* SendProcSignal() later to speed up the operation. Otherwise, don't do
158
* that because auxiliary processes (except the startup process) don't
159
* have a valid backend id.
160
*/
161
if
(proc != NULL)
162
backendId = proc->
backendId
;
163
else
164
proc =
AuxiliaryPidGetProc
(pid);
165
166
/*
167
* BackendPidGetProc() and AuxiliaryPidGetProc() return NULL if the pid
168
* isn't valid; but by the time we reach kill(), a process for which we
169
* get a valid proc here might have terminated on its own. There's no way
170
* to acquire a lock on an arbitrary process to prevent that. But since
171
* this mechanism is usually used to debug a backend or an auxiliary
172
* process running and consuming lots of memory, that it might end on its
173
* own first and its memory contexts are not logged is not a problem.
174
*/
175
if
(proc == NULL)
176
{
177
/*
178
* This is just a warning so a loop-through-resultset will not abort
179
* if one backend terminated on its own during the run.
180
*/
181
ereport
(
WARNING
,
182
(
errmsg
(
"PID %d is not a PostgreSQL server process"
, pid)));
183
PG_RETURN_BOOL
(
false
);
184
}
185
186
if
(
SendProcSignal
(pid,
PROCSIG_LOG_MEMORY_CONTEXT
, backendId) < 0)
187
{
188
/* Again, just a warning to allow loops */
189
ereport
(
WARNING
,
190
(
errmsg
(
"could not send signal to process %d: %m"
, pid)));
191
PG_RETURN_BOOL
(
false
);
192
}
193
194
PG_RETURN_BOOL
(
true
);
195
}
BackendId
int BackendId
Definition:
backendid.h:21
InvalidBackendId
#define InvalidBackendId
Definition:
backendid.h:23
values
static Datum values[MAXATTR]
Definition:
bootstrap.c:156
builtins.h
CStringGetTextDatum
#define CStringGetTextDatum(s)
Definition:
builtins.h:94
errmsg
int errmsg(const char *fmt,...)
Definition:
elog.c:1069
WARNING
#define WARNING
Definition:
elog.h:36
ereport
#define ereport(elevel,...)
Definition:
elog.h:149
Int64GetDatum
Datum Int64GetDatum(int64 X)
Definition:
fmgr.c:1807
PG_GETARG_INT32
#define PG_GETARG_INT32(n)
Definition:
fmgr.h:269
PG_FUNCTION_ARGS
#define PG_FUNCTION_ARGS
Definition:
fmgr.h:193
PG_RETURN_BOOL
#define PG_RETURN_BOOL(x)
Definition:
fmgr.h:359
InitMaterializedSRF
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition:
funcapi.c:76
funcapi.h
ident
#define ident
Definition:
indent_codes.h:47
Assert
Assert(fmt[strlen(fmt) - 1] !='\n')
pg_mbcliplen
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition:
mbutils.c:1084
TopMemoryContext
MemoryContext TopMemoryContext
Definition:
mcxt.c:141
pg_log_backend_memory_contexts
Datum pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)
Definition:
mcxtfuncs.c:145
PG_GET_BACKEND_MEMORY_CONTEXTS_COLS
#define PG_GET_BACKEND_MEMORY_CONTEXTS_COLS
PutMemoryContextsStatsTupleStore
static void PutMemoryContextsStatsTupleStore(Tuplestorestate *tupstore, TupleDesc tupdesc, MemoryContext context, const char *parent, int level)
Definition:
mcxtfuncs.c:36
MEMORY_CONTEXT_IDENT_DISPLAY_SIZE
#define MEMORY_CONTEXT_IDENT_DISPLAY_SIZE
Definition:
mcxtfuncs.c:29
pg_get_backend_memory_contexts
Datum pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
Definition:
mcxtfuncs.c:120
MemoryContextIsValid
#define MemoryContextIsValid(context)
Definition:
memnodes.h:107
miscadmin.h
pg_wchar.h
postgres.h
Datum
uintptr_t Datum
Definition:
postgres.h:64
Int32GetDatum
static Datum Int32GetDatum(int32 X)
Definition:
postgres.h:212
proc.h
BackendPidGetProc
PGPROC * BackendPidGetProc(int pid)
Definition:
procarray.c:3102
procarray.h
SendProcSignal
int SendProcSignal(pid_t pid, ProcSignalReason reason, BackendId backendId)
Definition:
procsignal.c:262
PROCSIG_LOG_MEMORY_CONTEXT
@ PROCSIG_LOG_MEMORY_CONTEXT
Definition:
procsignal.h:37
AuxiliaryPidGetProc
PGPROC * AuxiliaryPidGetProc(int pid)
Definition:
proc.c:1000
MemoryContextCounters
Definition:
memnodes.h:30
MemoryContextData
Definition:
memnodes.h:80
MemoryContextData::firstchild
MemoryContext firstchild
Definition:
memnodes.h:90
MemoryContextData::ident
const char * ident
Definition:
memnodes.h:94
MemoryContextData::methods
const MemoryContextMethods * methods
Definition:
memnodes.h:88
MemoryContextData::nextchild
MemoryContext nextchild
Definition:
memnodes.h:92
MemoryContextData::name
const char * name
Definition:
memnodes.h:93
MemoryContextMethods::stats
void(* stats)(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
Definition:
memnodes.h:69
PGPROC
Definition:
proc.h:162
PGPROC::backendId
BackendId backendId
Definition:
proc.h:197
ReturnSetInfo
Definition:
execnodes.h:322
ReturnSetInfo::setDesc
TupleDesc setDesc
Definition:
execnodes.h:333
ReturnSetInfo::setResult
Tuplestorestate * setResult
Definition:
execnodes.h:332
TupleDescData
Definition:
tupdesc.h:80
Tuplestorestate
Definition:
tuplestore.c:104
stat
Definition:
win32_port.h:265
tuplestore_putvalues
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition:
tuplestore.c:750
name
const char * name
Definition:
wait_event_funcs.c:28
stat
#define stat
Definition:
win32_port.h:284
src
backend
utils
adt
mcxtfuncs.c
Generated on Mon Dec 11 2023 06:13:22 for PostgreSQL Source Code by
1.9.1