summaryrefslogtreecommitdiffstats
path: root/src/include/utils/backend_status.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/include/utils/backend_status.h')
-rw-r--r--src/include/utils/backend_status.h321
1 files changed, 321 insertions, 0 deletions
diff --git a/src/include/utils/backend_status.h b/src/include/utils/backend_status.h
new file mode 100644
index 0000000..8042b81
--- /dev/null
+++ b/src/include/utils/backend_status.h
@@ -0,0 +1,321 @@
+/* ----------
+ * backend_status.h
+ * Definitions related to backend status reporting
+ *
+ * Copyright (c) 2001-2021, PostgreSQL Global Development Group
+ *
+ * src/include/utils/backend_status.h
+ * ----------
+ */
+#ifndef BACKEND_STATUS_H
+#define BACKEND_STATUS_H
+
+#include "datatype/timestamp.h"
+#include "libpq/pqcomm.h"
+#include "miscadmin.h" /* for BackendType */
+#include "utils/backend_progress.h"
+
+
+/* ----------
+ * Backend states
+ * ----------
+ */
+typedef enum BackendState
+{
+ STATE_UNDEFINED,
+ STATE_IDLE,
+ STATE_RUNNING,
+ STATE_IDLEINTRANSACTION,
+ STATE_FASTPATH,
+ STATE_IDLEINTRANSACTION_ABORTED,
+ STATE_DISABLED
+} BackendState;
+
+
+/* ----------
+ * Shared-memory data structures
+ * ----------
+ */
+
+/*
+ * PgBackendSSLStatus
+ *
+ * For each backend, we keep the SSL status in a separate struct, that
+ * is only filled in if SSL is enabled.
+ *
+ * All char arrays must be null-terminated.
+ */
+typedef struct PgBackendSSLStatus
+{
+ /* Information about SSL connection */
+ int ssl_bits;
+ char ssl_version[NAMEDATALEN];
+ char ssl_cipher[NAMEDATALEN];
+ char ssl_client_dn[NAMEDATALEN];
+
+ /*
+ * serial number is max "20 octets" per RFC 5280, so this size should be
+ * fine
+ */
+ char ssl_client_serial[NAMEDATALEN];
+
+ char ssl_issuer_dn[NAMEDATALEN];
+} PgBackendSSLStatus;
+
+/*
+ * PgBackendGSSStatus
+ *
+ * For each backend, we keep the GSS status in a separate struct, that
+ * is only filled in if GSS is enabled.
+ *
+ * All char arrays must be null-terminated.
+ */
+typedef struct PgBackendGSSStatus
+{
+ /* Information about GSSAPI connection */
+ char gss_princ[NAMEDATALEN]; /* GSSAPI Principal used to auth */
+ bool gss_auth; /* If GSSAPI authentication was used */
+ bool gss_enc; /* If encryption is being used */
+
+} PgBackendGSSStatus;
+
+
+/* ----------
+ * PgBackendStatus
+ *
+ * Each live backend maintains a PgBackendStatus struct in shared memory
+ * showing its current activity. (The structs are allocated according to
+ * BackendId, but that is not critical.) Note that the collector process
+ * has no involvement in, or even access to, these structs.
+ *
+ * Each auxiliary process also maintains a PgBackendStatus struct in shared
+ * memory.
+ * ----------
+ */
+typedef struct PgBackendStatus
+{
+ /*
+ * To avoid locking overhead, we use the following protocol: a backend
+ * increments st_changecount before modifying its entry, and again after
+ * finishing a modification. A would-be reader should note the value of
+ * st_changecount, copy the entry into private memory, then check
+ * st_changecount again. If the value hasn't changed, and if it's even,
+ * the copy is valid; otherwise start over. This makes updates cheap
+ * while reads are potentially expensive, but that's the tradeoff we want.
+ *
+ * The above protocol needs memory barriers to ensure that the apparent
+ * order of execution is as it desires. Otherwise, for example, the CPU
+ * might rearrange the code so that st_changecount is incremented twice
+ * before the modification on a machine with weak memory ordering. Hence,
+ * use the macros defined below for manipulating st_changecount, rather
+ * than touching it directly.
+ */
+ int st_changecount;
+
+ /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
+ int st_procpid;
+
+ /* Type of backends */
+ BackendType st_backendType;
+
+ /* Times when current backend, transaction, and activity started */
+ TimestampTz st_proc_start_timestamp;
+ TimestampTz st_xact_start_timestamp;
+ TimestampTz st_activity_start_timestamp;
+ TimestampTz st_state_start_timestamp;
+
+ /* Database OID, owning user's OID, connection client address */
+ Oid st_databaseid;
+ Oid st_userid;
+ SockAddr st_clientaddr;
+ char *st_clienthostname; /* MUST be null-terminated */
+
+ /* Information about SSL connection */
+ bool st_ssl;
+ PgBackendSSLStatus *st_sslstatus;
+
+ /* Information about GSSAPI connection */
+ bool st_gss;
+ PgBackendGSSStatus *st_gssstatus;
+
+ /* current state */
+ BackendState st_state;
+
+ /* application name; MUST be null-terminated */
+ char *st_appname;
+
+ /*
+ * Current command string; MUST be null-terminated. Note that this string
+ * possibly is truncated in the middle of a multi-byte character. As
+ * activity strings are stored more frequently than read, that allows to
+ * move the cost of correct truncation to the display side. Use
+ * pgstat_clip_activity() to truncate correctly.
+ */
+ char *st_activity_raw;
+
+ /*
+ * Command progress reporting. Any command which wishes can advertise
+ * that it is running by setting st_progress_command,
+ * st_progress_command_target, and st_progress_param[].
+ * st_progress_command_target should be the OID of the relation which the
+ * command targets (we assume there's just one, as this is meant for
+ * utility commands), but the meaning of each element in the
+ * st_progress_param array is command-specific.
+ */
+ ProgressCommandType st_progress_command;
+ Oid st_progress_command_target;
+ int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
+
+ /* query identifier, optionally computed using post_parse_analyze_hook */
+ uint64 st_query_id;
+} PgBackendStatus;
+
+
+/*
+ * Macros to load and store st_changecount with appropriate memory barriers.
+ *
+ * Use PGSTAT_BEGIN_WRITE_ACTIVITY() before, and PGSTAT_END_WRITE_ACTIVITY()
+ * after, modifying the current process's PgBackendStatus data. Note that,
+ * since there is no mechanism for cleaning up st_changecount after an error,
+ * THESE MACROS FORM A CRITICAL SECTION. Any error between them will be
+ * promoted to PANIC, causing a database restart to clean up shared memory!
+ * Hence, keep the critical section as short and straight-line as possible.
+ * Aside from being safer, that minimizes the window in which readers will
+ * have to loop.
+ *
+ * Reader logic should follow this sketch:
+ *
+ * for (;;)
+ * {
+ * int before_ct, after_ct;
+ *
+ * pgstat_begin_read_activity(beentry, before_ct);
+ * ... copy beentry data to local memory ...
+ * pgstat_end_read_activity(beentry, after_ct);
+ * if (pgstat_read_activity_complete(before_ct, after_ct))
+ * break;
+ * CHECK_FOR_INTERRUPTS();
+ * }
+ *
+ * For extra safety, we generally use volatile beentry pointers, although
+ * the memory barriers should theoretically be sufficient.
+ */
+#define PGSTAT_BEGIN_WRITE_ACTIVITY(beentry) \
+ do { \
+ START_CRIT_SECTION(); \
+ (beentry)->st_changecount++; \
+ pg_write_barrier(); \
+ } while (0)
+
+#define PGSTAT_END_WRITE_ACTIVITY(beentry) \
+ do { \
+ pg_write_barrier(); \
+ (beentry)->st_changecount++; \
+ Assert(((beentry)->st_changecount & 1) == 0); \
+ END_CRIT_SECTION(); \
+ } while (0)
+
+#define pgstat_begin_read_activity(beentry, before_changecount) \
+ do { \
+ (before_changecount) = (beentry)->st_changecount; \
+ pg_read_barrier(); \
+ } while (0)
+
+#define pgstat_end_read_activity(beentry, after_changecount) \
+ do { \
+ pg_read_barrier(); \
+ (after_changecount) = (beentry)->st_changecount; \
+ } while (0)
+
+#define pgstat_read_activity_complete(before_changecount, after_changecount) \
+ ((before_changecount) == (after_changecount) && \
+ ((before_changecount) & 1) == 0)
+
+
+/* ----------
+ * LocalPgBackendStatus
+ *
+ * When we build the backend status array, we use LocalPgBackendStatus to be
+ * able to add new values to the struct when needed without adding new fields
+ * to the shared memory. It contains the backend status as a first member.
+ * ----------
+ */
+typedef struct LocalPgBackendStatus
+{
+ /*
+ * Local version of the backend status entry.
+ */
+ PgBackendStatus backendStatus;
+
+ /*
+ * The xid of the current transaction if available, InvalidTransactionId
+ * if not.
+ */
+ TransactionId backend_xid;
+
+ /*
+ * The xmin of the current session if available, InvalidTransactionId if
+ * not.
+ */
+ TransactionId backend_xmin;
+} LocalPgBackendStatus;
+
+
+/* ----------
+ * GUC parameters
+ * ----------
+ */
+extern PGDLLIMPORT bool pgstat_track_activities;
+extern PGDLLIMPORT int pgstat_track_activity_query_size;
+
+
+/* ----------
+ * Other global variables
+ * ----------
+ */
+extern PGDLLIMPORT PgBackendStatus *MyBEEntry;
+
+
+/* ----------
+ * Functions called from postmaster
+ * ----------
+ */
+extern Size BackendStatusShmemSize(void);
+extern void CreateSharedBackendStatus(void);
+
+
+/* ----------
+ * Functions called from backends
+ * ----------
+ */
+
+/* Initialization functions */
+extern void pgstat_beinit(void);
+extern void pgstat_bestart(void);
+
+extern void pgstat_clear_backend_activity_snapshot(void);
+
+/* Activity reporting functions */
+extern void pgstat_report_activity(BackendState state, const char *cmd_str);
+extern void pgstat_report_query_id(uint64 query_id, bool force);
+extern void pgstat_report_tempfile(size_t filesize);
+extern void pgstat_report_appname(const char *appname);
+extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
+extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
+extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
+ int buflen);
+extern uint64 pgstat_get_my_query_id(void);
+
+
+/* ----------
+ * Support functions for the SQL-callable functions to
+ * generate the pgstat* views.
+ * ----------
+ */
+extern int pgstat_fetch_stat_numbackends(void);
+extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
+extern LocalPgBackendStatus *pgstat_fetch_stat_local_beentry(int beid);
+extern char *pgstat_clip_activity(const char *raw_activity);
+
+
+#endif /* BACKEND_STATUS_H */