PostgreSQL Source Code git master
Loading...
Searching...
No Matches
backend_status.c File Reference
#include "postgres.h"
#include "access/xact.h"
#include "libpq/libpq-be.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "pgstat.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/shmem.h"
#include "storage/subsystems.h"
#include "utils/ascii.h"
#include "utils/guc.h"
#include "utils/memutils.h"
Include dependency graph for backend_status.c:

Go to the source code of this file.

Macros

#define NumBackendStatSlots   (MaxBackends + NUM_AUXILIARY_PROCS)
 

Functions

static void pgstat_beshutdown_hook (int code, Datum arg)
 
static void pgstat_read_current_status (void)
 
static void pgstat_setup_backend_status_context (void)
 
static void BackendStatusShmemRequest (void *arg)
 
static void BackendStatusShmemInit (void *arg)
 
static void BackendStatusShmemAttach (void *arg)
 
void pgstat_beinit (void)
 
void pgstat_bestart_initial (void)
 
void pgstat_bestart_security (void)
 
void pgstat_bestart_final (void)
 
void pgstat_clear_backend_activity_snapshot (void)
 
void pgstat_report_activity (BackendState state, const char *cmd_str)
 
void pgstat_report_query_id (int64 query_id, bool force)
 
void pgstat_report_plan_id (int64 plan_id, bool force)
 
void pgstat_report_appname (const char *appname)
 
void pgstat_report_xact_timestamp (TimestampTz tstamp)
 
const charpgstat_get_backend_current_activity (int pid, bool checkUser)
 
const charpgstat_get_crashed_backend_activity (int pid, char *buffer, int buflen)
 
int64 pgstat_get_my_query_id (void)
 
int64 pgstat_get_my_plan_id (void)
 
static int cmp_lbestatus (const void *a, const void *b)
 
PgBackendStatuspgstat_get_beentry_by_proc_number (ProcNumber procNumber)
 
LocalPgBackendStatuspgstat_get_local_beentry_by_proc_number (ProcNumber procNumber)
 
LocalPgBackendStatuspgstat_get_local_beentry_by_index (int idx)
 
int pgstat_fetch_stat_numbackends (void)
 
charpgstat_clip_activity (const char *raw_activity)
 

Variables

bool pgstat_track_activities = false
 
int pgstat_track_activity_query_size = 1024
 
PgBackendStatusMyBEEntry = NULL
 
static PgBackendStatusBackendStatusArray = NULL
 
static charBackendAppnameBuffer = NULL
 
static charBackendClientHostnameBuffer = NULL
 
static charBackendActivityBuffer = NULL
 
static Size BackendActivityBufferSize = 0
 
static LocalPgBackendStatuslocalBackendStatusTable = NULL
 
static int localNumBackends = 0
 
static MemoryContext backendStatusSnapContext
 
const ShmemCallbacks BackendStatusShmemCallbacks
 

Macro Definition Documentation

◆ NumBackendStatSlots

#define NumBackendStatSlots   (MaxBackends + NUM_AUXILIARY_PROCS)

Definition at line 37 of file backend_status.c.

Function Documentation

◆ BackendStatusShmemAttach()

static void BackendStatusShmemAttach ( void arg)
static

Definition at line 195 of file backend_status.c.

196{
199}
#define NumBackendStatSlots
static Size BackendActivityBufferSize
int pgstat_track_activity_query_size
Size mul_size(Size s1, Size s2)
Definition shmem.c:1058

References BackendActivityBufferSize, mul_size(), NumBackendStatSlots, and pgstat_track_activity_query_size.

◆ BackendStatusShmemInit()

static void BackendStatusShmemInit ( void arg)
static

Definition at line 136 of file backend_status.c.

137{
138 int i;
139 char *buffer;
140
141 /* Initialize st_appname pointers. */
142 buffer = BackendAppnameBuffer;
143 for (i = 0; i < NumBackendStatSlots; i++)
144 {
146 buffer += NAMEDATALEN;
147 }
148
149 /* Initialize st_clienthostname pointers. */
151 for (i = 0; i < NumBackendStatSlots; i++)
152 {
154 buffer += NAMEDATALEN;
155 }
156
157 /* Initialize st_activity pointers. */
158 buffer = BackendActivityBuffer;
159 for (i = 0; i < NumBackendStatSlots; i++)
160 {
163 }
164
165#ifdef USE_SSL
166 {
168
169 /* Initialize st_sslstatus pointers. */
171 for (i = 0; i < NumBackendStatSlots; i++)
172 {
174 ptr++;
175 }
176 }
177#endif
178
179#ifdef ENABLE_GSS
180 {
182
183 /* Initialize st_gssstatus pointers. */
185 for (i = 0; i < NumBackendStatSlots; i++)
186 {
188 ptr++;
189 }
190 }
191#endif
192}
static char * BackendClientHostnameBuffer
static char * BackendActivityBuffer
static char * BackendAppnameBuffer
static PgBackendStatus * BackendStatusArray
int i
Definition isn.c:77
#define NAMEDATALEN
static int fb(int x)
PgBackendGSSStatus * st_gssstatus
PgBackendSSLStatus * st_sslstatus

References BackendActivityBuffer, BackendAppnameBuffer, BackendClientHostnameBuffer, BackendStatusArray, fb(), i, NAMEDATALEN, NumBackendStatSlots, pgstat_track_activity_query_size, PgBackendStatus::st_activity_raw, PgBackendStatus::st_appname, PgBackendStatus::st_clienthostname, PgBackendStatus::st_gssstatus, and PgBackendStatus::st_sslstatus.

◆ BackendStatusShmemRequest()

static void BackendStatusShmemRequest ( void arg)
static

Definition at line 92 of file backend_status.c.

93{
94 ShmemRequestStruct(.name = "Backend Status Array",
96 .ptr = (void **) &BackendStatusArray,
97 );
98
99 ShmemRequestStruct(.name = "Backend Application Name Buffer",
101 .ptr = (void **) &BackendAppnameBuffer,
102 );
103
104 ShmemRequestStruct(.name = "Backend Client Host Name Buffer",
106 .ptr = (void **) &BackendClientHostnameBuffer,
107 );
108
111 ShmemRequestStruct(.name = "Backend Activity Buffer",
113 .ptr = (void **) &BackendActivityBuffer
114 );
115
116#ifdef USE_SSL
117 ShmemRequestStruct(.name = "Backend SSL Status Buffer",
119 .ptr = (void **) &BackendSslStatusBuffer,
120 );
121#endif
122
123#ifdef ENABLE_GSS
124 ShmemRequestStruct(.name = "Backend GSS Status Buffer",
126 .ptr = (void **) &BackendGssStatusBuffer,
127 );
128#endif
129}
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name

References BackendActivityBuffer, BackendActivityBufferSize, BackendAppnameBuffer, BackendClientHostnameBuffer, BackendStatusArray, fb(), mul_size(), name, NAMEDATALEN, NumBackendStatSlots, pgstat_track_activity_query_size, and ShmemRequestStruct.

◆ cmp_lbestatus()

static int cmp_lbestatus ( const void a,
const void b 
)
static

Definition at line 1140 of file backend_status.c.

1141{
1144
1145 return lbestatus1->proc_number - lbestatus2->proc_number;
1146}
int b
Definition isn.c:74
int a
Definition isn.c:73

References a, b, fb(), and LocalPgBackendStatus::proc_number.

Referenced by pgstat_get_local_beentry_by_proc_number().

◆ pgstat_beinit()

void pgstat_beinit ( void  )

Definition at line 210 of file backend_status.c.

211{
212 /* Initialize MyBEEntry */
216
217 /* Set up a process-exit hook to clean up */
219}
PgBackendStatus * MyBEEntry
static void pgstat_beshutdown_hook(int code, Datum arg)
#define Assert(condition)
Definition c.h:943
ProcNumber MyProcNumber
Definition globals.c:90
void on_shmem_exit(pg_on_exit_callback function, Datum arg)
Definition ipc.c:372
#define INVALID_PROC_NUMBER
Definition procnumber.h:26

References Assert, BackendStatusArray, INVALID_PROC_NUMBER, MyBEEntry, MyProcNumber, NumBackendStatSlots, on_shmem_exit(), and pgstat_beshutdown_hook().

Referenced by AuxiliaryProcessMainCommon(), and InitPostgres().

◆ pgstat_beshutdown_hook()

static void pgstat_beshutdown_hook ( int  code,
Datum  arg 
)
static

Definition at line 474 of file backend_status.c.

475{
477
478 /*
479 * Clear my status entry, following the protocol of bumping st_changecount
480 * before and after. We use a volatile pointer here to ensure the
481 * compiler doesn't try to get cute.
482 */
484
485 beentry->st_procpid = 0; /* mark invalid */
486
488
489 /* so that functions can check if backend_status.c is up via MyBEEntry */
490 MyBEEntry = NULL;
491}
#define PGSTAT_END_WRITE_ACTIVITY(beentry)
#define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry)

References fb(), MyBEEntry, PGSTAT_BEGIN_WRITE_ACTIVITY, and PGSTAT_END_WRITE_ACTIVITY.

Referenced by pgstat_beinit().

◆ pgstat_bestart_final()

void pgstat_bestart_final ( void  )

Definition at line 432 of file backend_status.c.

433{
435 Oid userid;
436
437 /* pgstats state must be initialized from pgstat_beinit() */
438 Assert(beentry != NULL);
439
440 /* We have userid for client-backends, wal-sender and bgworker processes */
444 userid = GetSessionUserId();
445 else
446 userid = InvalidOid;
447
448 /*
449 * Update my status entry, following the protocol of bumping
450 * st_changecount before and after. We use a volatile pointer here to
451 * ensure the compiler doesn't try to get cute.
452 */
454
455 beentry->st_databaseid = MyDatabaseId;
456 beentry->st_userid = userid;
457 beentry->st_state = STATE_UNDEFINED;
458
460
461 /* Create the backend statistics entry */
464
465 /* Update app name to current GUC setting */
468}
void pgstat_report_appname(const char *appname)
@ STATE_UNDEFINED
Oid MyDatabaseId
Definition globals.c:94
char * application_name
Definition guc_tables.c:579
@ B_WAL_SENDER
Definition miscadmin.h:347
@ B_BG_WORKER
Definition miscadmin.h:346
@ B_BACKEND
Definition miscadmin.h:342
Oid GetSessionUserId(void)
Definition miscinit.c:509
BackendType MyBackendType
Definition miscinit.c:65
void pgstat_create_backend(ProcNumber procnum)
bool pgstat_tracks_backend_bktype(BackendType bktype)
#define InvalidOid
unsigned int Oid

References application_name, Assert, B_BACKEND, B_BG_WORKER, B_WAL_SENDER, fb(), GetSessionUserId(), InvalidOid, MyBackendType, MyBEEntry, MyDatabaseId, MyProcNumber, PGSTAT_BEGIN_WRITE_ACTIVITY, pgstat_create_backend(), PGSTAT_END_WRITE_ACTIVITY, pgstat_report_appname(), pgstat_tracks_backend_bktype(), and STATE_UNDEFINED.

Referenced by AuxiliaryProcessMainCommon(), and InitPostgres().

◆ pgstat_bestart_initial()

void pgstat_bestart_initial ( void  )

Definition at line 235 of file backend_status.c.

236{
239
240 /* pgstats state must be initialized from pgstat_beinit() */
241 Assert(vbeentry != NULL);
242
243 /*
244 * To minimize the time spent modifying the PgBackendStatus entry, and
245 * avoid risk of errors inside the critical section, we first copy the
246 * shared-memory struct to a local variable, then modify the data in the
247 * local variable, then copy the local variable back to shared memory.
248 * Only the last step has to be inside the critical section.
249 *
250 * Most of the data we copy from shared memory is just going to be
251 * overwritten, but the struct's not so large that it's worth the
252 * maintenance hassle to copy only the needful fields.
253 */
256 sizeof(PgBackendStatus));
257
258 /*
259 * Now fill in all the fields of lbeentry, except for strings that are
260 * out-of-line data. Those have to be handled separately, below.
261 */
262 lbeentry.st_procpid = MyProcPid;
263 lbeentry.st_backendType = MyBackendType;
264 lbeentry.st_proc_start_timestamp = MyStartTimestamp;
265 lbeentry.st_activity_start_timestamp = 0;
266 lbeentry.st_state_start_timestamp = 0;
267 lbeentry.st_xact_start_timestamp = 0;
268 lbeentry.st_databaseid = InvalidOid;
269 lbeentry.st_userid = InvalidOid;
270
271 /*
272 * We may not have a MyProcPort (eg, if this is the autovacuum process).
273 * If so, use all-zeroes client address, which is dealt with specially in
274 * pg_stat_get_backend_client_addr and pg_stat_get_backend_client_port.
275 */
276 if (MyProcPort)
277 memcpy(&lbeentry.st_clientaddr, &MyProcPort->raddr,
278 sizeof(lbeentry.st_clientaddr));
279 else
280 MemSet(&lbeentry.st_clientaddr, 0, sizeof(lbeentry.st_clientaddr));
281
282 lbeentry.st_ssl = false;
283 lbeentry.st_gss = false;
284
285 lbeentry.st_state = STATE_STARTING;
286 lbeentry.st_progress_command = PROGRESS_COMMAND_INVALID;
287 lbeentry.st_progress_command_target = InvalidOid;
288 lbeentry.st_query_id = INT64CONST(0);
289 lbeentry.st_plan_id = INT64CONST(0);
290
291 /*
292 * we don't zero st_progress_param here to save cycles; nobody should
293 * examine it until st_progress_command has been set to something other
294 * than PROGRESS_COMMAND_INVALID
295 */
296
297 /*
298 * We're ready to enter the critical section that fills the shared-memory
299 * status entry. We follow the protocol of bumping st_changecount before
300 * and after; and make sure it's even afterwards. We use a volatile
301 * pointer here to ensure the compiler doesn't try to get cute.
302 */
304
305 /* make sure we'll memcpy the same st_changecount back */
306 lbeentry.st_changecount = vbeentry->st_changecount;
307
309 &lbeentry,
310 sizeof(PgBackendStatus));
311
312 /*
313 * We can write the out-of-line strings and structs using the pointers
314 * that are in lbeentry; this saves some de-volatilizing messiness.
315 */
316 lbeentry.st_appname[0] = '\0';
318 strlcpy(lbeentry.st_clienthostname, MyProcPort->remote_hostname,
320 else
321 lbeentry.st_clienthostname[0] = '\0';
322 lbeentry.st_activity_raw[0] = '\0';
323 /* Also make sure the last byte in each string area is always 0 */
324 lbeentry.st_appname[NAMEDATALEN - 1] = '\0';
325 lbeentry.st_clienthostname[NAMEDATALEN - 1] = '\0';
326 lbeentry.st_activity_raw[pgstat_track_activity_query_size - 1] = '\0';
327
328 /* These structs can just start from zeroes each time */
329#ifdef USE_SSL
330 memset(lbeentry.st_sslstatus, 0, sizeof(PgBackendSSLStatus));
331#endif
332#ifdef ENABLE_GSS
333 memset(lbeentry.st_gssstatus, 0, sizeof(PgBackendGSSStatus));
334#endif
335
337}
@ PROGRESS_COMMAND_INVALID
@ STATE_STARTING
#define INT64CONST(x)
Definition c.h:630
#define unvolatize(underlying_type, expr)
Definition c.h:1328
#define MemSet(start, val, len)
Definition c.h:1107
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
int MyProcPid
Definition globals.c:47
TimestampTz MyStartTimestamp
Definition globals.c:49
struct Port * MyProcPort
Definition globals.c:51
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
char * remote_hostname
Definition libpq-be.h:136
SockAddr raddr
Definition libpq-be.h:134

References Assert, fb(), INT64CONST, InvalidOid, memcpy(), MemSet, MyBackendType, MyBEEntry, MyProcPid, MyProcPort, MyStartTimestamp, NAMEDATALEN, PGSTAT_BEGIN_WRITE_ACTIVITY, PGSTAT_END_WRITE_ACTIVITY, pgstat_track_activity_query_size, PROGRESS_COMMAND_INVALID, Port::raddr, Port::remote_hostname, STATE_STARTING, strlcpy(), and unvolatize.

Referenced by AuxiliaryProcessMainCommon(), and InitPostgres().

◆ pgstat_bestart_security()

void pgstat_bestart_security ( void  )

Definition at line 350 of file backend_status.c.

351{
353 bool ssl = false;
354 bool gss = false;
355#ifdef USE_SSL
357 PgBackendSSLStatus *st_sslstatus;
358#endif
359#ifdef ENABLE_GSS
361 PgBackendGSSStatus *st_gssstatus;
362#endif
363
364 /* pgstats state must be initialized from pgstat_beinit() */
365 Assert(beentry != NULL);
366 Assert(MyProcPort); /* otherwise there's no point */
367
368#ifdef USE_SSL
369 st_sslstatus = beentry->st_sslstatus;
370 memset(&lsslstatus, 0, sizeof(lsslstatus));
371
373 {
374 ssl = true;
381 }
382#endif
383
384#ifdef ENABLE_GSS
385 st_gssstatus = beentry->st_gssstatus;
386 memset(&lgssstatus, 0, sizeof(lgssstatus));
387
388 if (MyProcPort->gss != NULL)
389 {
390 const char *princ = be_gssapi_get_princ(MyProcPort);
391
392 gss = true;
396 if (princ)
397 strlcpy(lgssstatus.gss_princ, princ, NAMEDATALEN);
398 }
399#endif
400
401 /*
402 * Update my status entry, following the protocol of bumping
403 * st_changecount before and after. We use a volatile pointer here to
404 * ensure the compiler doesn't try to get cute.
405 */
407
408 beentry->st_ssl = ssl;
409 beentry->st_gss = gss;
410
411#ifdef USE_SSL
412 memcpy(st_sslstatus, &lsslstatus, sizeof(PgBackendSSLStatus));
413#endif
414#ifdef ENABLE_GSS
415 memcpy(st_gssstatus, &lgssstatus, sizeof(PgBackendGSSStatus));
416#endif
417
419}
bool be_gssapi_get_auth(Port *port)
bool be_gssapi_get_enc(Port *port)
const char * be_gssapi_get_princ(Port *port)
bool be_gssapi_get_delegation(Port *port)
const char * be_tls_get_version(Port *port)
int be_tls_get_cipher_bits(Port *port)
const char * be_tls_get_cipher(Port *port)
void be_tls_get_peer_serial(Port *port, char *ptr, size_t len)
void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len)
void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len)
bool ssl_in_use
Definition libpq-be.h:208
void * gss
Definition libpq-be.h:202

References Assert, be_gssapi_get_auth(), be_gssapi_get_delegation(), be_gssapi_get_enc(), be_gssapi_get_princ(), be_tls_get_cipher(), be_tls_get_cipher_bits(), be_tls_get_peer_issuer_name(), be_tls_get_peer_serial(), be_tls_get_peer_subject_name(), be_tls_get_version(), fb(), Port::gss, memcpy(), MyBEEntry, MyProcPort, NAMEDATALEN, PGSTAT_BEGIN_WRITE_ACTIVITY, PGSTAT_END_WRITE_ACTIVITY, Port::ssl_in_use, and strlcpy().

Referenced by InitPostgres().

◆ pgstat_clear_backend_activity_snapshot()

void pgstat_clear_backend_activity_snapshot ( void  )

Definition at line 501 of file backend_status.c.

502{
503 /* Release memory, if any was allocated */
505 {
508 }
509
510 /* Reset variables */
513}
static LocalPgBackendStatus * localBackendStatusTable
static int localNumBackends
static MemoryContext backendStatusSnapContext
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472

References backendStatusSnapContext, fb(), localBackendStatusTable, localNumBackends, and MemoryContextDelete().

Referenced by pgstat_clear_snapshot().

◆ pgstat_clip_activity()

char * pgstat_clip_activity ( const char raw_activity)

Definition at line 1255 of file backend_status.c.

1256{
1257 char *activity;
1258 int rawlen;
1259 int cliplen;
1260
1261 /*
1262 * Some callers, like pgstat_get_backend_current_activity(), do not
1263 * guarantee that the buffer isn't concurrently modified. We try to take
1264 * care that the buffer is always terminated by a NUL byte regardless, but
1265 * let's still be paranoid about the string's length. In those cases the
1266 * underlying buffer is guaranteed to be pgstat_track_activity_query_size
1267 * large.
1268 */
1270
1271 /* now double-guaranteed to be NUL terminated */
1273
1274 /*
1275 * All supported server-encodings make it possible to determine the length
1276 * of a multi-byte character from its first byte (this is not the case for
1277 * client encodings, see GB18030). As st_activity is always stored using
1278 * server encoding, this allows us to perform multi-byte aware truncation,
1279 * even if the string earlier was truncated in the middle of a multi-byte
1280 * character.
1281 */
1284
1285 activity[cliplen] = '\0';
1286
1287 return activity;
1288}
int pg_mbcliplen(const char *mbstr, int len, int limit)
Definition mbutils.c:1211
static int cliplen(const char *str, int len, int limit)
Definition mbutils.c:1278
char * pnstrdup(const char *in, Size len)
Definition mcxt.c:1792

References cliplen(), fb(), pg_mbcliplen(), pgstat_track_activity_query_size, and pnstrdup().

Referenced by pg_stat_get_activity(), pg_stat_get_backend_activity(), and pgstat_get_backend_current_activity().

◆ pgstat_fetch_stat_numbackends()

int pgstat_fetch_stat_numbackends ( void  )

Definition at line 1239 of file backend_status.c.

1240{
1242
1243 return localNumBackends;
1244}
static void pgstat_read_current_status(void)

References localNumBackends, and pgstat_read_current_status().

Referenced by pg_stat_get_activity(), pg_stat_get_backend_idset(), pg_stat_get_db_numbackends(), and pg_stat_get_progress_info().

◆ pgstat_get_backend_current_activity()

const char * pgstat_get_backend_current_activity ( int  pid,
bool  checkUser 
)

Definition at line 961 of file backend_status.c.

962{
964 int i;
965
967 for (i = 1; i <= MaxBackends; i++)
968 {
969 /*
970 * Although we expect the target backend's entry to be stable, that
971 * doesn't imply that anyone else's is. To avoid identifying the
972 * wrong backend, while we check for a match to the desired PID we
973 * must follow the protocol of retrying if st_changecount changes
974 * while we examine the entry, or if it's odd. (This might be
975 * unnecessary, since fetching or storing an int is almost certainly
976 * atomic, but let's play it safe.) We use a volatile pointer here to
977 * ensure the compiler doesn't try to get cute.
978 */
979 volatile PgBackendStatus *vbeentry = beentry;
980 bool found;
981
982 for (;;)
983 {
986
988
989 found = (vbeentry->st_procpid == pid);
990
992
995 break;
996
997 /* Make sure we can break out of loop if stuck... */
999 }
1000
1001 if (found)
1002 {
1003 /* Now it is safe to use the non-volatile pointer */
1004 if (checkUser && !superuser() && beentry->st_userid != GetUserId())
1005 return "<insufficient privilege>";
1006 else if (*(beentry->st_activity_raw) == '\0')
1007 return "<command string not enabled>";
1008 else
1009 {
1010 /* this'll leak a bit of memory, but that seems acceptable */
1011 return pgstat_clip_activity(beentry->st_activity_raw);
1012 }
1013 }
1014
1015 beentry++;
1016 }
1017
1018 /* If we get here, caller is in error ... */
1019 return "<backend information not available>";
1020}
char * pgstat_clip_activity(const char *raw_activity)
#define pgstat_read_activity_complete(before_changecount, after_changecount)
#define pgstat_end_read_activity(beentry, after_changecount)
#define pgstat_begin_read_activity(beentry, before_changecount)
int MaxBackends
Definition globals.c:146
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
Oid GetUserId(void)
Definition miscinit.c:470
bool superuser(void)
Definition superuser.c:47

References BackendStatusArray, CHECK_FOR_INTERRUPTS, fb(), GetUserId(), i, MaxBackends, pgstat_begin_read_activity, pgstat_clip_activity(), pgstat_end_read_activity, pgstat_read_activity_complete, and superuser().

Referenced by DeadLockReport().

◆ pgstat_get_beentry_by_proc_number()

◆ pgstat_get_crashed_backend_activity()

const char * pgstat_get_crashed_backend_activity ( int  pid,
char buffer,
int  buflen 
)

Definition at line 1039 of file backend_status.c.

1040{
1041 volatile PgBackendStatus *beentry;
1042 int i;
1043
1045
1046 /*
1047 * We probably shouldn't get here before shared memory has been set up,
1048 * but be safe.
1049 */
1051 return NULL;
1052
1053 for (i = 1; i <= MaxBackends; i++)
1054 {
1055 if (beentry->st_procpid == pid)
1056 {
1057 /* Read pointer just once, so it can't change after validation */
1058 const char *activity = beentry->st_activity_raw;
1059 const char *activity_last;
1060
1061 /*
1062 * We mustn't access activity string before we verify that it
1063 * falls within the BackendActivityBuffer. To make sure that the
1064 * entire string including its ending is contained within the
1065 * buffer, subtract one activity length from the buffer size.
1066 */
1069
1072 return NULL;
1073
1074 /* If no string available, no point in a report */
1075 if (activity[0] == '\0')
1076 return NULL;
1077
1078 /*
1079 * Copy only ASCII-safe characters so we don't run into encoding
1080 * problems when reporting the message; and be sure not to run off
1081 * the end of memory. As only ASCII characters are reported, it
1082 * doesn't seem necessary to perform multibyte aware clipping.
1083 */
1086
1087 return buffer;
1088 }
1089
1090 beentry++;
1091 }
1092
1093 /* PID not found */
1094 return NULL;
1095}
void ascii_safe_strlcpy(char *dest, const char *src, size_t destsiz)
Definition ascii.c:174
#define Min(x, y)
Definition c.h:1091

References ascii_safe_strlcpy(), BackendActivityBuffer, BackendActivityBufferSize, BackendStatusArray, fb(), i, MaxBackends, Min, pgstat_track_activity_query_size, and PgBackendStatus::st_activity_raw.

Referenced by LogChildExit().

◆ pgstat_get_local_beentry_by_index()

LocalPgBackendStatus * pgstat_get_local_beentry_by_index ( int  idx)

◆ pgstat_get_local_beentry_by_proc_number()

LocalPgBackendStatus * pgstat_get_local_beentry_by_proc_number ( ProcNumber  procNumber)

Definition at line 1188 of file backend_status.c.

1189{
1191
1193
1194 /*
1195 * Since the localBackendStatusTable is in order by proc_number, we can
1196 * use bsearch() to search it efficiently.
1197 */
1198 key.proc_number = procNumber;
1201}
static int cmp_lbestatus(const void *a, const void *b)

References cmp_lbestatus(), fb(), localBackendStatusTable, localNumBackends, and pgstat_read_current_status().

Referenced by pg_stat_get_backend_subxact(), and pgstat_get_beentry_by_proc_number().

◆ pgstat_get_my_plan_id()

int64 pgstat_get_my_plan_id ( void  )

Definition at line 1123 of file backend_status.c.

1124{
1125 if (!MyBEEntry)
1126 return 0;
1127
1128 /* No need for a lock, for roughly the same reasons as above. */
1129 return MyBEEntry->st_plan_id;
1130}

References MyBEEntry, and PgBackendStatus::st_plan_id.

Referenced by ExecSerializePlan().

◆ pgstat_get_my_query_id()

int64 pgstat_get_my_query_id ( void  )

Definition at line 1103 of file backend_status.c.

1104{
1105 if (!MyBEEntry)
1106 return 0;
1107
1108 /*
1109 * There's no need for a lock around pgstat_begin_read_activity /
1110 * pgstat_end_read_activity here as it's only called from
1111 * pg_stat_get_activity which is already protected, or from the same
1112 * backend which means that there won't be concurrent writes.
1113 */
1114 return MyBEEntry->st_query_id;
1115}

References MyBEEntry, and PgBackendStatus::st_query_id.

Referenced by _brin_begin_parallel(), _bt_begin_parallel(), ExecSerializePlan(), log_status_format(), parallel_vacuum_init(), write_csvlog(), and write_jsonlog().

◆ pgstat_read_current_status()

static void pgstat_read_current_status ( void  )
static

Definition at line 785 of file backend_status.c.

786{
787 volatile PgBackendStatus *beentry;
790 char *localappname,
793#ifdef USE_SSL
795#endif
796#ifdef ENABLE_GSS
798#endif
799 ProcNumber procNumber;
800
802 return; /* already done */
803
805
806 /*
807 * Allocate storage for local copy of state data. We can presume that
808 * none of these requests overflow size_t, because we already calculated
809 * the same values using mul_size during shmem setup. However, with
810 * probably-silly values of pgstat_track_activity_query_size and
811 * max_connections, the localactivity buffer could exceed 1GB, so use
812 * "huge" allocation for that one.
813 */
817 localappname = (char *)
820 localclienthostname = (char *)
823 localactivity = (char *)
827#ifdef USE_SSL
831#endif
832#ifdef ENABLE_GSS
836#endif
837
839
842 for (procNumber = 0; procNumber < NumBackendStatSlots; procNumber++)
843 {
844 /*
845 * Follow the protocol of retrying if st_changecount changes while we
846 * copy the entry, or if it's odd. (The check for odd is needed to
847 * cover the case where we are able to completely copy the entry while
848 * the source backend is between increment steps.) We use a volatile
849 * pointer here to ensure the compiler doesn't try to get cute.
850 */
851 for (;;)
852 {
855
857
858 localentry->backendStatus.st_procpid = beentry->st_procpid;
859 /* Skip all the data-copying work if entry is not in use */
860 if (localentry->backendStatus.st_procpid > 0)
861 {
862 memcpy(&localentry->backendStatus, unvolatize(PgBackendStatus *, beentry), sizeof(PgBackendStatus));
863
864 /*
865 * For each PgBackendStatus field that is a pointer, copy the
866 * pointed-to data, then adjust the local copy of the pointer
867 * field to point at the local copy of the data.
868 *
869 * strcpy is safe even if the string is modified concurrently,
870 * because there's always a \0 at the end of the buffer.
871 */
872 strcpy(localappname, beentry->st_appname);
873 localentry->backendStatus.st_appname = localappname;
874 strcpy(localclienthostname, beentry->st_clienthostname);
875 localentry->backendStatus.st_clienthostname = localclienthostname;
876 strcpy(localactivity, beentry->st_activity_raw);
877 localentry->backendStatus.st_activity_raw = localactivity;
878#ifdef USE_SSL
879 if (beentry->st_ssl)
880 {
881 memcpy(localsslstatus, beentry->st_sslstatus, sizeof(PgBackendSSLStatus));
882 localentry->backendStatus.st_sslstatus = localsslstatus;
883 }
884#endif
885#ifdef ENABLE_GSS
886 if (beentry->st_gss)
887 {
888 memcpy(localgssstatus, beentry->st_gssstatus, sizeof(PgBackendGSSStatus));
889 localentry->backendStatus.st_gssstatus = localgssstatus;
890 }
891#endif
892 }
893
895
898 break;
899
900 /* Make sure we can break out of loop if stuck... */
902 }
903
904 /* Only valid entries get included into the local array */
905 if (localentry->backendStatus.st_procpid > 0)
906 {
907 /*
908 * The BackendStatusArray index is exactly the ProcNumber of the
909 * source backend. Note that this means localBackendStatusTable
910 * is in order by proc_number. pgstat_get_beentry_by_proc_number()
911 * depends on that.
912 */
913 localentry->proc_number = procNumber;
915 &localentry->backend_xid,
916 &localentry->backend_xmin,
917 &localentry->backend_subxact_count,
918 &localentry->backend_subxact_overflowed);
919
920 localentry++;
924#ifdef USE_SSL
926#endif
927#ifdef ENABLE_GSS
929#endif
931 }
932
933 beentry++;
934 }
935
936 /* Set the pointer only after completion of a valid table */
938}
static void pgstat_setup_backend_status_context(void)
size_t Size
Definition c.h:689
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
void * MemoryContextAllocHuge(MemoryContext context, Size size)
Definition mcxt.c:1725
void ProcNumberGetTransactionIds(ProcNumber procNumber, TransactionId *xid, TransactionId *xmin, int *nsubxid, bool *overflowed)
Definition procarray.c:3112
int ProcNumber
Definition procnumber.h:24

References BackendStatusArray, backendStatusSnapContext, CHECK_FOR_INTERRUPTS, fb(), localBackendStatusTable, localNumBackends, memcpy(), MemoryContextAlloc(), MemoryContextAllocHuge(), NAMEDATALEN, NumBackendStatSlots, pgstat_begin_read_activity, pgstat_end_read_activity, pgstat_read_activity_complete, pgstat_setup_backend_status_context(), pgstat_track_activity_query_size, ProcNumberGetTransactionIds(), and unvolatize.

Referenced by pgstat_fetch_stat_numbackends(), pgstat_get_local_beentry_by_index(), and pgstat_get_local_beentry_by_proc_number().

◆ pgstat_report_activity()

void pgstat_report_activity ( BackendState  state,
const char cmd_str 
)

Definition at line 537 of file backend_status.c.

538{
542 int len = 0;
543
545
546 if (!beentry)
547 return;
548
550 {
551 if (beentry->st_state != STATE_DISABLED)
552 {
553 volatile PGPROC *proc = MyProc;
554
555 /*
556 * track_activities is disabled, but we last reported a
557 * non-disabled state. As our final update, change the state and
558 * clear fields we will not be updating anymore.
559 */
561 beentry->st_state = STATE_DISABLED;
562 beentry->st_state_start_timestamp = 0;
563 beentry->st_activity_raw[0] = '\0';
564 beentry->st_activity_start_timestamp = 0;
565 /* st_xact_start_timestamp and wait_event_info are also disabled */
566 beentry->st_xact_start_timestamp = 0;
567 beentry->st_query_id = INT64CONST(0);
568 beentry->st_plan_id = INT64CONST(0);
569 proc->wait_event_info = 0;
571 }
572 return;
573 }
574
575 /*
576 * To minimize the time spent modifying the entry, and avoid risk of
577 * errors inside the critical section, fetch all the needed data first.
578 */
580 if (cmd_str != NULL)
581 {
582 /*
583 * Compute length of to-be-stored string unaware of multi-byte
584 * characters. For speed reasons that'll get corrected on read, rather
585 * than computed every write.
586 */
588 }
590
591 /*
592 * If the state has changed from "active" or "idle in transaction",
593 * calculate the duration.
594 */
595 if ((beentry->st_state == STATE_RUNNING ||
596 beentry->st_state == STATE_FASTPATH ||
597 beentry->st_state == STATE_IDLEINTRANSACTION ||
599 state != beentry->st_state)
600 {
601 long secs;
602 int usecs;
603
604 TimestampDifference(beentry->st_state_start_timestamp,
606 &secs, &usecs);
607
608 if (beentry->st_state == STATE_RUNNING ||
609 beentry->st_state == STATE_FASTPATH)
611 else
613 }
614
615 /*
616 * Now update the status entry
617 */
619
620 beentry->st_state = state;
621 beentry->st_state_start_timestamp = current_timestamp;
622
623 /*
624 * If a new query is started, we reset the query identifier as it'll only
625 * be known after parse analysis, to avoid reporting last query's
626 * identifier.
627 */
628 if (state == STATE_RUNNING)
629 {
630 beentry->st_query_id = INT64CONST(0);
631 beentry->st_plan_id = INT64CONST(0);
632 }
633
634 if (cmd_str != NULL)
635 {
636 memcpy(beentry->st_activity_raw, cmd_str, len);
637 beentry->st_activity_raw[len] = '\0';
638 beentry->st_activity_start_timestamp = start_timestamp;
639 }
640
642}
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition timestamp.c:1715
TimestampTz GetCurrentTimestamp(void)
Definition timestamp.c:1639
bool pgstat_track_activities
@ STATE_IDLEINTRANSACTION_ABORTED
@ STATE_IDLEINTRANSACTION
@ STATE_DISABLED
@ STATE_FASTPATH
@ STATE_RUNNING
int64 TimestampTz
Definition timestamp.h:39
const void size_t len
#define pgstat_count_conn_txn_idle_time(n)
Definition pgstat.h:664
#define pgstat_count_conn_active_time(n)
Definition pgstat.h:662
int64 PgStat_Counter
Definition pgstat.h:71
PGPROC * MyProc
Definition proc.c:71
Definition proc.h:179
uint32 wait_event_info
Definition proc.h:378
TimestampTz GetCurrentStatementStartTimestamp(void)
Definition xact.c:881

References fb(), GetCurrentStatementStartTimestamp(), GetCurrentTimestamp(), INT64CONST, len, memcpy(), Min, MyBEEntry, MyProc, PGSTAT_BEGIN_WRITE_ACTIVITY, pgstat_count_conn_active_time, pgstat_count_conn_txn_idle_time, PGSTAT_END_WRITE_ACTIVITY, pgstat_track_activities, pgstat_track_activity_query_size, STATE_DISABLED, STATE_FASTPATH, STATE_IDLEINTRANSACTION, STATE_IDLEINTRANSACTION_ABORTED, STATE_RUNNING, TimestampDifference(), and PGPROC::wait_event_info.

Referenced by _brin_parallel_build_main(), _bt_parallel_build_main(), _gin_parallel_build_main(), apply_handle_begin(), apply_handle_begin_prepare(), apply_handle_commit(), apply_handle_commit_prepared(), apply_handle_prepare(), apply_handle_rollback_prepared(), apply_handle_stream_commit(), apply_handle_stream_prepare(), apply_handle_stream_start(), apply_handle_stream_stop(), apply_spooled_messages(), autovac_report_activity(), autovac_report_workitem(), DataChecksumsWorkerMain(), exec_bind_message(), exec_execute_message(), exec_parse_message(), exec_replication_command(), exec_simple_query(), initialize_worker_spi(), LogicalRepApplyLoop(), pa_stream_abort(), parallel_vacuum_main(), ParallelQueryMain(), PostgresMain(), ProcessDatabase(), ProcessSingleRelationByOid(), ProcessSingleRelationFork(), WaitForAllTransactionsToFinish(), and worker_spi_main().

◆ pgstat_report_appname()

void pgstat_report_appname ( const char appname)

Definition at line 729 of file backend_status.c.

730{
732 int len;
733
734 if (!beentry)
735 return;
736
737 /* This should be unnecessary if GUC did its job, but be safe */
738 len = pg_mbcliplen(appname, strlen(appname), NAMEDATALEN - 1);
739
740 /*
741 * Update my status entry, following the protocol of bumping
742 * st_changecount before and after. We use a volatile pointer here to
743 * ensure the compiler doesn't try to get cute.
744 */
746
747 memcpy(beentry->st_appname, appname, len);
748 beentry->st_appname[len] = '\0';
749
751}

References fb(), len, memcpy(), MyBEEntry, NAMEDATALEN, pg_mbcliplen(), PGSTAT_BEGIN_WRITE_ACTIVITY, and PGSTAT_END_WRITE_ACTIVITY.

Referenced by assign_application_name(), and pgstat_bestart_final().

◆ pgstat_report_plan_id()

void pgstat_report_plan_id ( int64  plan_id,
bool  force 
)

Definition at line 690 of file backend_status.c.

691{
693
694 /*
695 * if track_activities is disabled, st_plan_id should already have been
696 * reset
697 */
699 return;
700
701 /*
702 * We only report the top-level plan identifiers. The stored plan_id is
703 * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
704 * with an explicit call to this function using the force flag. If the
705 * saved plan identifier is not zero it means that it's not a top-level
706 * command, so ignore the one provided unless it's an explicit call to
707 * reset the identifier.
708 */
709 if (beentry->st_plan_id != 0 && !force)
710 return;
711
712 /*
713 * Update my status entry, following the protocol of bumping
714 * st_changecount before and after. We use a volatile pointer here to
715 * ensure the compiler doesn't try to get cute.
716 */
718 beentry->st_plan_id = plan_id;
720}

References fb(), MyBEEntry, PGSTAT_BEGIN_WRITE_ACTIVITY, PGSTAT_END_WRITE_ACTIVITY, and pgstat_track_activities.

Referenced by exec_bind_message(), exec_execute_message(), exec_simple_query(), and planner().

◆ pgstat_report_query_id()

void pgstat_report_query_id ( int64  query_id,
bool  force 
)

Definition at line 651 of file backend_status.c.

652{
654
655 /*
656 * if track_activities is disabled, st_query_id should already have been
657 * reset
658 */
660 return;
661
662 /*
663 * We only report the top-level query identifiers. The stored query_id is
664 * reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
665 * with an explicit call to this function using the force flag. If the
666 * saved query identifier is not zero it means that it's not a top-level
667 * command, so ignore the one provided unless it's an explicit call to
668 * reset the identifier.
669 */
670 if (beentry->st_query_id != INT64CONST(0) && !force)
671 return;
672
673 /*
674 * Update my status entry, following the protocol of bumping
675 * st_changecount before and after. We use a volatile pointer here to
676 * ensure the compiler doesn't try to get cute.
677 */
679 beentry->st_query_id = query_id;
681}

References fb(), INT64CONST, MyBEEntry, PGSTAT_BEGIN_WRITE_ACTIVITY, PGSTAT_END_WRITE_ACTIVITY, and pgstat_track_activities.

Referenced by _brin_parallel_build_main(), _bt_parallel_build_main(), exec_bind_message(), exec_execute_message(), exec_simple_query(), ExecutorStart(), parallel_vacuum_main(), parse_analyze_fixedparams(), parse_analyze_varparams(), and parse_analyze_withcb().

◆ pgstat_report_xact_timestamp()

void pgstat_report_xact_timestamp ( TimestampTz  tstamp)

Definition at line 758 of file backend_status.c.

759{
761
763 return;
764
765 /*
766 * Update my status entry, following the protocol of bumping
767 * st_changecount before and after. We use a volatile pointer here to
768 * ensure the compiler doesn't try to get cute.
769 */
771
772 beentry->st_xact_start_timestamp = tstamp;
773
775}

References fb(), MyBEEntry, PGSTAT_BEGIN_WRITE_ACTIVITY, PGSTAT_END_WRITE_ACTIVITY, and pgstat_track_activities.

Referenced by AbortTransaction(), CommitTransaction(), PrepareTransaction(), and StartTransaction().

◆ pgstat_setup_backend_status_context()

static void pgstat_setup_backend_status_context ( void  )
static

Definition at line 516 of file backend_status.c.

517{
520 "Backend Status Snapshot",
522}
MemoryContext TopMemoryContext
Definition mcxt.c:166
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_SMALL_SIZES
Definition memutils.h:170

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, backendStatusSnapContext, and TopMemoryContext.

Referenced by pgstat_read_current_status().

Variable Documentation

◆ BackendActivityBuffer

char* BackendActivityBuffer = NULL
static

◆ BackendActivityBufferSize

Size BackendActivityBufferSize = 0
static

◆ BackendAppnameBuffer

char* BackendAppnameBuffer = NULL
static

Definition at line 53 of file backend_status.c.

Referenced by BackendStatusShmemInit(), and BackendStatusShmemRequest().

◆ BackendClientHostnameBuffer

char* BackendClientHostnameBuffer = NULL
static

Definition at line 54 of file backend_status.c.

Referenced by BackendStatusShmemInit(), and BackendStatusShmemRequest().

◆ BackendStatusArray

◆ BackendStatusShmemCallbacks

const ShmemCallbacks BackendStatusShmemCallbacks
Initial value:
= {
}
static void BackendStatusShmemRequest(void *arg)
static void BackendStatusShmemInit(void *arg)
static void BackendStatusShmemAttach(void *arg)

Definition at line 82 of file backend_status.c.

82 {
83 .request_fn = BackendStatusShmemRequest,
84 .init_fn = BackendStatusShmemInit,
85 .attach_fn = BackendStatusShmemAttach,
86};

◆ backendStatusSnapContext

◆ localBackendStatusTable

◆ localNumBackends

◆ MyBEEntry

◆ pgstat_track_activities

◆ pgstat_track_activity_query_size