diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index ef1cba61a6..6757df397c 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -198,8 +198,6 @@ static time_t last_pgstat_start_time; static bool pgStatRunningInCollector = false; -static PgStat_SubXactStatus *pgStatXactStack = NULL; - /* * Info about current "snapshot" of stats file */ @@ -740,158 +738,6 @@ pgstat_initialize(void) } -/* ------------------------------------------------------------ - * Transaction integration - * ------------------------------------------------------------ - */ - -/* - * Called from access/transam/xact.c at top-level transaction commit/abort. - */ -void -AtEOXact_PgStat(bool isCommit, bool parallel) -{ - PgStat_SubXactStatus *xact_state; - - AtEOXact_PgStat_Database(isCommit, parallel); - - /* handle transactional stats information */ - xact_state = pgStatXactStack; - if (xact_state != NULL) - { - Assert(xact_state->nest_level == 1); - Assert(xact_state->prev == NULL); - - AtEOXact_PgStat_Relations(xact_state, isCommit); - } - pgStatXactStack = NULL; - - /* Make sure any stats snapshot is thrown away */ - pgstat_clear_snapshot(); -} - -/* - * Called from access/transam/xact.c at subtransaction commit/abort. - */ -void -AtEOSubXact_PgStat(bool isCommit, int nestDepth) -{ - PgStat_SubXactStatus *xact_state; - - /* merge the sub-transaction's transactional stats into the parent */ - xact_state = pgStatXactStack; - if (xact_state != NULL && - xact_state->nest_level >= nestDepth) - { - /* delink xact_state from stack immediately to simplify reuse case */ - pgStatXactStack = xact_state->prev; - - AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth); - - pfree(xact_state); - } -} - -/* - * Save the transactional stats state at 2PC transaction prepare. - */ -void -AtPrepare_PgStat(void) -{ - PgStat_SubXactStatus *xact_state; - - xact_state = pgStatXactStack; - if (xact_state != NULL) - { - Assert(xact_state->nest_level == 1); - Assert(xact_state->prev == NULL); - - AtPrepare_PgStat_Relations(xact_state); - } -} - -/* - * Clean up after successful PREPARE. - * - * Note: AtEOXact_PgStat is not called during PREPARE. - */ -void -PostPrepare_PgStat(void) -{ - PgStat_SubXactStatus *xact_state; - - /* - * We don't bother to free any of the transactional state, since it's all - * in TopTransactionContext and will go away anyway. - */ - xact_state = pgStatXactStack; - if (xact_state != NULL) - { - Assert(xact_state->nest_level == 1); - Assert(xact_state->prev == NULL); - - PostPrepare_PgStat_Relations(xact_state); - } - pgStatXactStack = NULL; - - /* Make sure any stats snapshot is thrown away */ - pgstat_clear_snapshot(); -} - -/* - * Discard any data collected in the current transaction. Any subsequent - * request will cause new snapshots to be read. - * - * This is also invoked during transaction commit or abort to discard - * the no-longer-wanted snapshot. - */ -void -pgstat_clear_snapshot(void) -{ - pgstat_assert_is_up(); - - /* Release memory, if any was allocated */ - if (pgStatLocalContext) - MemoryContextDelete(pgStatLocalContext); - - /* Reset variables */ - pgStatLocalContext = NULL; - pgStatDBHash = NULL; - replSlotStatHash = NULL; - subscriptionStatHash = NULL; - - /* - * Historically the backend_status.c facilities lived in this file, and - * were reset with the same function. For now keep it that way, and - * forward the reset request. - */ - pgstat_clear_backend_activity_snapshot(); -} - -/* - * Ensure (sub)transaction stack entry for the given nest_level exists, adding - * it if needed. - */ -PgStat_SubXactStatus * -pgstat_xact_stack_level_get(int nest_level) -{ - PgStat_SubXactStatus *xact_state; - - xact_state = pgStatXactStack; - if (xact_state == NULL || xact_state->nest_level != nest_level) - { - xact_state = (PgStat_SubXactStatus *) - MemoryContextAlloc(TopTransactionContext, - sizeof(PgStat_SubXactStatus)); - xact_state->nest_level = nest_level; - xact_state->prev = pgStatXactStack; - xact_state->first = NULL; - pgStatXactStack = xact_state; - } - return xact_state; -} - - /* ------------------------------------------------------------ * Public functions used by backends follow * ------------------------------------------------------------ @@ -1319,6 +1165,36 @@ pgstat_send_inquiry(TimestampTz clock_time, TimestampTz cutoff_time, Oid databas pgstat_send(&msg, sizeof(msg)); } +/* + * Discard any data collected in the current transaction. Any subsequent + * request will cause new snapshots to be read. + * + * This is also invoked during transaction commit or abort to discard + * the no-longer-wanted snapshot. + */ +void +pgstat_clear_snapshot(void) +{ + pgstat_assert_is_up(); + + /* Release memory, if any was allocated */ + if (pgStatLocalContext) + MemoryContextDelete(pgStatLocalContext); + + /* Reset variables */ + pgStatLocalContext = NULL; + pgStatDBHash = NULL; + replSlotStatHash = NULL; + subscriptionStatHash = NULL; + + /* + * Historically the backend_status.c facilities lived in this file, and + * were reset with the same function. For now keep it that way, and + * forward the reset request. + */ + pgstat_clear_backend_activity_snapshot(); +} + /* * Support function for the SQL-callable pgstat* functions. Returns * the collected statistics for one database or NULL. NULL doesn't mean diff --git a/src/backend/utils/activity/Makefile b/src/backend/utils/activity/Makefile index 25a967ab7d..791ba68e7e 100644 --- a/src/backend/utils/activity/Makefile +++ b/src/backend/utils/activity/Makefile @@ -23,9 +23,10 @@ OBJS = \ pgstat_function.o \ pgstat_relation.o \ pgstat_replslot.o \ + pgstat_slru.o \ pgstat_subscription.o \ pgstat_wal.o \ - pgstat_slru.o \ + pgstat_xact.o \ wait_event.o include $(top_srcdir)/src/backend/common.mk diff --git a/src/backend/utils/activity/pgstat_xact.c b/src/backend/utils/activity/pgstat_xact.c new file mode 100644 index 0000000000..17907e3278 --- /dev/null +++ b/src/backend/utils/activity/pgstat_xact.c @@ -0,0 +1,139 @@ +/* ------------------------------------------------------------------------- + * + * pgstat_xact.c + * Transactional integration for the cumulative statistics system. + * + * Copyright (c) 2001-2022, PostgreSQL Global Development Group + * + * IDENTIFICATION + * src/backend/utils/activity/pgstat_xact.c + * ------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/transam.h" +#include "access/xact.h" +#include "pgstat.h" +#include "utils/memutils.h" +#include "utils/pgstat_internal.h" + + +static PgStat_SubXactStatus *pgStatXactStack = NULL; + + +/* + * Called from access/transam/xact.c at top-level transaction commit/abort. + */ +void +AtEOXact_PgStat(bool isCommit, bool parallel) +{ + PgStat_SubXactStatus *xact_state; + + AtEOXact_PgStat_Database(isCommit, parallel); + + /* handle transactional stats information */ + xact_state = pgStatXactStack; + if (xact_state != NULL) + { + Assert(xact_state->nest_level == 1); + Assert(xact_state->prev == NULL); + + AtEOXact_PgStat_Relations(xact_state, isCommit); + } + pgStatXactStack = NULL; + + /* Make sure any stats snapshot is thrown away */ + pgstat_clear_snapshot(); +} + +/* + * Called from access/transam/xact.c at subtransaction commit/abort. + */ +void +AtEOSubXact_PgStat(bool isCommit, int nestDepth) +{ + PgStat_SubXactStatus *xact_state; + + /* merge the sub-transaction's transactional stats into the parent */ + xact_state = pgStatXactStack; + if (xact_state != NULL && + xact_state->nest_level >= nestDepth) + { + /* delink xact_state from stack immediately to simplify reuse case */ + pgStatXactStack = xact_state->prev; + + AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth); + + pfree(xact_state); + } +} + +/* + * Save the transactional stats state at 2PC transaction prepare. + */ +void +AtPrepare_PgStat(void) +{ + PgStat_SubXactStatus *xact_state; + + xact_state = pgStatXactStack; + if (xact_state != NULL) + { + Assert(xact_state->nest_level == 1); + Assert(xact_state->prev == NULL); + + AtPrepare_PgStat_Relations(xact_state); + } +} + +/* + * Clean up after successful PREPARE. + * + * Note: AtEOXact_PgStat is not called during PREPARE. + */ +void +PostPrepare_PgStat(void) +{ + PgStat_SubXactStatus *xact_state; + + /* + * We don't bother to free any of the transactional state, since it's all + * in TopTransactionContext and will go away anyway. + */ + xact_state = pgStatXactStack; + if (xact_state != NULL) + { + Assert(xact_state->nest_level == 1); + Assert(xact_state->prev == NULL); + + PostPrepare_PgStat_Relations(xact_state); + } + pgStatXactStack = NULL; + + /* Make sure any stats snapshot is thrown away */ + pgstat_clear_snapshot(); +} + +/* + * Ensure (sub)transaction stack entry for the given nest_level exists, adding + * it if needed. + */ +PgStat_SubXactStatus * +pgstat_xact_stack_level_get(int nest_level) +{ + PgStat_SubXactStatus *xact_state; + + xact_state = pgStatXactStack; + if (xact_state == NULL || xact_state->nest_level != nest_level) + { + xact_state = (PgStat_SubXactStatus *) + MemoryContextAlloc(TopTransactionContext, + sizeof(PgStat_SubXactStatus)); + xact_state->nest_level = nest_level; + xact_state->prev = pgStatXactStack; + xact_state->first = NULL; + pgStatXactStack = xact_state; + } + return xact_state; +} diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 41fdf5f5a3..95bf06f829 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -969,13 +969,6 @@ extern void PgstatCollectorMain(int argc, char *argv[]) pg_attribute_noreturn(); /* Functions for backend initialization */ extern void pgstat_initialize(void); -/* transactional integration */ -extern void AtEOXact_PgStat(bool isCommit, bool parallel); -extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth); -extern void AtPrepare_PgStat(void); -extern void PostPrepare_PgStat(void); -extern void pgstat_clear_snapshot(void); - /* Functions called from backends */ extern void pgstat_report_stat(bool force); extern void pgstat_vacuum_stat(void); @@ -986,6 +979,7 @@ extern void pgstat_reset_single_counter(Oid objectid, PgStat_Single_Reset_Type t extern void pgstat_reset_shared_counters(const char *); /* stats accessors */ +extern void pgstat_clear_snapshot(void); extern PgStat_ArchiverStats *pgstat_fetch_stat_archiver(void); extern PgStat_BgWriterStats *pgstat_fetch_stat_bgwriter(void); extern PgStat_CheckpointerStats *pgstat_fetch_stat_checkpointer(void); @@ -1157,6 +1151,16 @@ extern void pgstat_report_subscription_error(Oid subid, bool is_apply_error); extern void pgstat_report_subscription_drop(Oid subid); +/* + * Functions in pgstat_xact.c + */ + +extern void AtEOXact_PgStat(bool isCommit, bool parallel); +extern void AtEOSubXact_PgStat(bool isCommit, int nestDepth); +extern void AtPrepare_PgStat(void); +extern void PostPrepare_PgStat(void); + + /* * Functions in pgstat_wal.c */ diff --git a/src/include/utils/pgstat_internal.h b/src/include/utils/pgstat_internal.h index abbb4f8d96..6a828e3aa0 100644 --- a/src/include/utils/pgstat_internal.h +++ b/src/include/utils/pgstat_internal.h @@ -77,7 +77,6 @@ static const char *const slru_names[] = { * Functions in pgstat.c */ -extern PgStat_SubXactStatus *pgstat_xact_stack_level_get(int nest_level); extern void pgstat_setheader(PgStat_MsgHdr *hdr, StatMsgType mtype); extern void pgstat_send(void *msg, int len); #ifdef USE_ASSERT_CHECKING @@ -129,6 +128,13 @@ extern void pgstat_wal_initialize(void); extern bool pgstat_wal_pending(void); +/* + * Functions in pgstat_xact.c + */ + +extern PgStat_SubXactStatus *pgstat_xact_stack_level_get(int nest_level); + + /* * Variables in pgstat.c */