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