mirror of
https://github.com/postgres/postgres.git
synced 2025-11-19 13:42:17 +03:00
uint64 was chosen to be consistent with the type used by the query ID, but the conclusion of a recent discussion for the query ID is that int64 is a better fit as the signed form is shown to the user, for PGSS or EXPLAIN outputs. This commit changes the plan ID to use int64, followingc3eda50b06that has done the same for the query ID. The plan ID is new to v18, introduced in2a0cd38da5. Author: Michael Paquier <michael@paquier.xyz> Reviewed-by: Sami Imseih <samimseih@gmail.com> Discussion: https://postgr.es/m/aCvzJNwetyEI3Sgo@paquier.xyz
350 lines
10 KiB
C
350 lines
10 KiB
C
/* ----------
|
|
* backend_status.h
|
|
* Definitions related to backend status reporting
|
|
*
|
|
* Copyright (c) 2001-2025, 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 "storage/procnumber.h"
|
|
#include "utils/backend_progress.h"
|
|
|
|
|
|
/* ----------
|
|
* Backend states
|
|
* ----------
|
|
*/
|
|
typedef enum BackendState
|
|
{
|
|
STATE_UNDEFINED,
|
|
STATE_STARTING,
|
|
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 */
|
|
bool gss_delegation; /* If credentials delegated */
|
|
|
|
} PgBackendGSSStatus;
|
|
|
|
|
|
/* ----------
|
|
* PgBackendStatus
|
|
*
|
|
* Each live backend maintains a PgBackendStatus struct in shared memory
|
|
* showing its current activity. (The structs are allocated according to
|
|
* ProcNumber, but that is not critical.) Note that this is unrelated to the
|
|
* cumulative stats system (i.e. pgstat.c et al).
|
|
*
|
|
* 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 */
|
|
int64 st_query_id;
|
|
|
|
/* plan identifier, optionally computed using planner_hook */
|
|
int64 st_plan_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 proc number.
|
|
*/
|
|
ProcNumber proc_number;
|
|
|
|
/*
|
|
* 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;
|
|
|
|
/*
|
|
* Number of cached subtransactions in the current session.
|
|
*/
|
|
int backend_subxact_count;
|
|
|
|
/*
|
|
* The number of subtransactions in the current session which exceeded the
|
|
* cached subtransaction limit.
|
|
*/
|
|
bool backend_subxact_overflowed;
|
|
} 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 BackendStatusShmemInit(void);
|
|
|
|
|
|
/* ----------
|
|
* Functions called from backends
|
|
* ----------
|
|
*/
|
|
|
|
/* Initialization functions */
|
|
extern void pgstat_beinit(void);
|
|
extern void pgstat_bestart_initial(void);
|
|
extern void pgstat_bestart_security(void);
|
|
extern void pgstat_bestart_final(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(int64 query_id, bool force);
|
|
extern void pgstat_report_plan_id(int64 plan_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 int64 pgstat_get_my_query_id(void);
|
|
extern int64 pgstat_get_my_plan_id(void);
|
|
extern BackendType pgstat_get_backend_type_by_proc_number(ProcNumber procNumber);
|
|
|
|
|
|
/* ----------
|
|
* Support functions for the SQL-callable functions to
|
|
* generate the pgstat* views.
|
|
* ----------
|
|
*/
|
|
extern int pgstat_fetch_stat_numbackends(void);
|
|
extern PgBackendStatus *pgstat_get_beentry_by_proc_number(ProcNumber procNumber);
|
|
extern LocalPgBackendStatus *pgstat_get_local_beentry_by_proc_number(ProcNumber procNumber);
|
|
extern LocalPgBackendStatus *pgstat_get_local_beentry_by_index(int idx);
|
|
extern char *pgstat_clip_activity(const char *raw_activity);
|
|
|
|
|
|
#endif /* BACKEND_STATUS_H */
|