1 /* ----------
2  * backend_status.h
3  *	  Definitions related to backend status reporting
4  *
5  * Copyright (c) 2001-2021, PostgreSQL Global Development Group
6  *
7  * src/include/utils/backend_status.h
8  * ----------
9  */
10 #ifndef BACKEND_STATUS_H
11 #define BACKEND_STATUS_H
12 
13 #include "datatype/timestamp.h"
14 #include "libpq/pqcomm.h"
15 #include "miscadmin.h"			/* for BackendType */
16 #include "utils/backend_progress.h"
17 
18 
19 /* ----------
20  * Backend states
21  * ----------
22  */
23 typedef enum BackendState
24 {
25 	STATE_UNDEFINED,
26 	STATE_IDLE,
27 	STATE_RUNNING,
28 	STATE_IDLEINTRANSACTION,
29 	STATE_FASTPATH,
30 	STATE_IDLEINTRANSACTION_ABORTED,
31 	STATE_DISABLED
32 } BackendState;
33 
34 
35 /* ----------
36  * Shared-memory data structures
37  * ----------
38  */
39 
40 /*
41  * PgBackendSSLStatus
42  *
43  * For each backend, we keep the SSL status in a separate struct, that
44  * is only filled in if SSL is enabled.
45  *
46  * All char arrays must be null-terminated.
47  */
48 typedef struct PgBackendSSLStatus
49 {
50 	/* Information about SSL connection */
51 	int			ssl_bits;
52 	char		ssl_version[NAMEDATALEN];
53 	char		ssl_cipher[NAMEDATALEN];
54 	char		ssl_client_dn[NAMEDATALEN];
55 
56 	/*
57 	 * serial number is max "20 octets" per RFC 5280, so this size should be
58 	 * fine
59 	 */
60 	char		ssl_client_serial[NAMEDATALEN];
61 
62 	char		ssl_issuer_dn[NAMEDATALEN];
63 } PgBackendSSLStatus;
64 
65 /*
66  * PgBackendGSSStatus
67  *
68  * For each backend, we keep the GSS status in a separate struct, that
69  * is only filled in if GSS is enabled.
70  *
71  * All char arrays must be null-terminated.
72  */
73 typedef struct PgBackendGSSStatus
74 {
75 	/* Information about GSSAPI connection */
76 	char		gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
77 	bool		gss_auth;		/* If GSSAPI authentication was used */
78 	bool		gss_enc;		/* If encryption is being used */
79 
80 } PgBackendGSSStatus;
81 
82 
83 /* ----------
84  * PgBackendStatus
85  *
86  * Each live backend maintains a PgBackendStatus struct in shared memory
87  * showing its current activity.  (The structs are allocated according to
88  * BackendId, but that is not critical.)  Note that the collector process
89  * has no involvement in, or even access to, these structs.
90  *
91  * Each auxiliary process also maintains a PgBackendStatus struct in shared
92  * memory.
93  * ----------
94  */
95 typedef struct PgBackendStatus
96 {
97 	/*
98 	 * To avoid locking overhead, we use the following protocol: a backend
99 	 * increments st_changecount before modifying its entry, and again after
100 	 * finishing a modification.  A would-be reader should note the value of
101 	 * st_changecount, copy the entry into private memory, then check
102 	 * st_changecount again.  If the value hasn't changed, and if it's even,
103 	 * the copy is valid; otherwise start over.  This makes updates cheap
104 	 * while reads are potentially expensive, but that's the tradeoff we want.
105 	 *
106 	 * The above protocol needs memory barriers to ensure that the apparent
107 	 * order of execution is as it desires.  Otherwise, for example, the CPU
108 	 * might rearrange the code so that st_changecount is incremented twice
109 	 * before the modification on a machine with weak memory ordering.  Hence,
110 	 * use the macros defined below for manipulating st_changecount, rather
111 	 * than touching it directly.
112 	 */
113 	int			st_changecount;
114 
115 	/* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
116 	int			st_procpid;
117 
118 	/* Type of backends */
119 	BackendType st_backendType;
120 
121 	/* Times when current backend, transaction, and activity started */
122 	TimestampTz st_proc_start_timestamp;
123 	TimestampTz st_xact_start_timestamp;
124 	TimestampTz st_activity_start_timestamp;
125 	TimestampTz st_state_start_timestamp;
126 
127 	/* Database OID, owning user's OID, connection client address */
128 	Oid			st_databaseid;
129 	Oid			st_userid;
130 	SockAddr	st_clientaddr;
131 	char	   *st_clienthostname;	/* MUST be null-terminated */
132 
133 	/* Information about SSL connection */
134 	bool		st_ssl;
135 	PgBackendSSLStatus *st_sslstatus;
136 
137 	/* Information about GSSAPI connection */
138 	bool		st_gss;
139 	PgBackendGSSStatus *st_gssstatus;
140 
141 	/* current state */
142 	BackendState st_state;
143 
144 	/* application name; MUST be null-terminated */
145 	char	   *st_appname;
146 
147 	/*
148 	 * Current command string; MUST be null-terminated. Note that this string
149 	 * possibly is truncated in the middle of a multi-byte character. As
150 	 * activity strings are stored more frequently than read, that allows to
151 	 * move the cost of correct truncation to the display side. Use
152 	 * pgstat_clip_activity() to truncate correctly.
153 	 */
154 	char	   *st_activity_raw;
155 
156 	/*
157 	 * Command progress reporting.  Any command which wishes can advertise
158 	 * that it is running by setting st_progress_command,
159 	 * st_progress_command_target, and st_progress_param[].
160 	 * st_progress_command_target should be the OID of the relation which the
161 	 * command targets (we assume there's just one, as this is meant for
162 	 * utility commands), but the meaning of each element in the
163 	 * st_progress_param array is command-specific.
164 	 */
165 	ProgressCommandType st_progress_command;
166 	Oid			st_progress_command_target;
167 	int64		st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
168 
169 	/* query identifier, optionally computed using post_parse_analyze_hook */
170 	uint64		st_query_id;
171 } PgBackendStatus;
172 
173 
174 /*
175  * Macros to load and store st_changecount with appropriate memory barriers.
176  *
177  * Use PGSTAT_BEGIN_WRITE_ACTIVITY() before, and PGSTAT_END_WRITE_ACTIVITY()
178  * after, modifying the current process's PgBackendStatus data.  Note that,
179  * since there is no mechanism for cleaning up st_changecount after an error,
180  * THESE MACROS FORM A CRITICAL SECTION.  Any error between them will be
181  * promoted to PANIC, causing a database restart to clean up shared memory!
182  * Hence, keep the critical section as short and straight-line as possible.
183  * Aside from being safer, that minimizes the window in which readers will
184  * have to loop.
185  *
186  * Reader logic should follow this sketch:
187  *
188  *		for (;;)
189  *		{
190  *			int before_ct, after_ct;
191  *
192  *			pgstat_begin_read_activity(beentry, before_ct);
193  *			... copy beentry data to local memory ...
194  *			pgstat_end_read_activity(beentry, after_ct);
195  *			if (pgstat_read_activity_complete(before_ct, after_ct))
196  *				break;
197  *			CHECK_FOR_INTERRUPTS();
198  *		}
199  *
200  * For extra safety, we generally use volatile beentry pointers, although
201  * the memory barriers should theoretically be sufficient.
202  */
203 #define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry) \
204 	do { \
205 		START_CRIT_SECTION(); \
206 		(beentry)->st_changecount++; \
207 		pg_write_barrier(); \
208 	} while (0)
209 
210 #define PGSTAT_END_WRITE_ACTIVITY(beentry) \
211 	do { \
212 		pg_write_barrier(); \
213 		(beentry)->st_changecount++; \
214 		Assert(((beentry)->st_changecount & 1) == 0); \
215 		END_CRIT_SECTION(); \
216 	} while (0)
217 
218 #define pgstat_begin_read_activity(beentry, before_changecount) \
219 	do { \
220 		(before_changecount) = (beentry)->st_changecount; \
221 		pg_read_barrier(); \
222 	} while (0)
223 
224 #define pgstat_end_read_activity(beentry, after_changecount) \
225 	do { \
226 		pg_read_barrier(); \
227 		(after_changecount) = (beentry)->st_changecount; \
228 	} while (0)
229 
230 #define pgstat_read_activity_complete(before_changecount, after_changecount) \
231 	((before_changecount) == (after_changecount) && \
232 	 ((before_changecount) & 1) == 0)
233 
234 
235 /* ----------
236  * LocalPgBackendStatus
237  *
238  * When we build the backend status array, we use LocalPgBackendStatus to be
239  * able to add new values to the struct when needed without adding new fields
240  * to the shared memory. It contains the backend status as a first member.
241  * ----------
242  */
243 typedef struct LocalPgBackendStatus
244 {
245 	/*
246 	 * Local version of the backend status entry.
247 	 */
248 	PgBackendStatus backendStatus;
249 
250 	/*
251 	 * The xid of the current transaction if available, InvalidTransactionId
252 	 * if not.
253 	 */
254 	TransactionId backend_xid;
255 
256 	/*
257 	 * The xmin of the current session if available, InvalidTransactionId if
258 	 * not.
259 	 */
260 	TransactionId backend_xmin;
261 } LocalPgBackendStatus;
262 
263 
264 /* ----------
265  * GUC parameters
266  * ----------
267  */
268 extern PGDLLIMPORT bool pgstat_track_activities;
269 extern PGDLLIMPORT int pgstat_track_activity_query_size;
270 
271 
272 /* ----------
273  * Other global variables
274  * ----------
275  */
276 extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
277 
278 
279 /* ----------
280  * Functions called from postmaster
281  * ----------
282  */
283 extern Size BackendStatusShmemSize(void);
284 extern void CreateSharedBackendStatus(void);
285 
286 
287 /* ----------
288  * Functions called from backends
289  * ----------
290  */
291 
292 /* Initialization functions */
293 extern void pgstat_beinit(void);
294 extern void pgstat_bestart(void);
295 
296 extern void pgstat_clear_backend_activity_snapshot(void);
297 
298 /* Activity reporting functions */
299 extern void pgstat_report_activity(BackendState state, const char *cmd_str);
300 extern void pgstat_report_query_id(uint64 query_id, bool force);
301 extern void pgstat_report_tempfile(size_t filesize);
302 extern void pgstat_report_appname(const char *appname);
303 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
304 extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
305 extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
306 													   int buflen);
307 extern uint64 pgstat_get_my_query_id(void);
308 
309 
310 /* ----------
311  * Support functions for the SQL-callable functions to
312  * generate the pgstat* views.
313  * ----------
314  */
315 extern int	pgstat_fetch_stat_numbackends(void);
316 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
317 extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
318 extern char *pgstat_clip_activity(const char *raw_activity);
319 
320 
321 #endif							/* BACKEND_STATUS_H */
322