1/* -------------------------------------------------------------------------
4 * Transactional integration for the cumulative statistics system.
6 * Copyright (c) 2001-2025, PostgreSQL Global Development Group
9 * src/backend/utils/activity/pgstat_xact.c
10 * -------------------------------------------------------------------------
31 bool isCommit,
int nestDepth);
37 * Called from access/transam/xact.c at top-level transaction commit/abort.
46 /* handle transactional stats information */
48 if (xact_state != NULL)
58 /* Make sure any stats snapshot is thrown away */
63 * When committing, drop stats for objects dropped in the transaction. When
64 * aborting, drop stats for objects created in the transaction.
70 int not_freed_count = 0;
85 * Transaction that dropped an object committed. Drop the stats
94 * Transaction that created an object aborted. Drop the stats
95 * associated with the object.
105 if (not_freed_count > 0)
110 * Called from access/transam/xact.c at subtransaction commit/abort.
117 /* merge the sub-transaction's transactional stats into the parent */
119 if (xact_state != NULL &&
122 /* delink xact_state from stack immediately to simplify reuse case */
133 * Like AtEOXact_PgStat_DroppedStats(), but for subtransactions.
137 bool isCommit,
int nestDepth)
141 int not_freed_count = 0;
160 * Subtransaction creating a new stats object aborted. Drop the
170 * Subtransaction dropping a stats object committed. Can't yet
171 * remove the stats object, the surrounding transaction might
172 * still abort. Pass it on to the parent.
183 if (not_freed_count > 0)
188 * Save the transactional stats state at 2PC transaction prepare.
196 if (xact_state != NULL)
206 * Clean up after successful PREPARE.
208 * Note: AtEOXact_PgStat is not called during PREPARE.
216 * We don't bother to free any of the transactional state, since it's all
217 * in TopTransactionContext and will go away anyway.
220 if (xact_state != NULL)
229 /* Make sure any stats snapshot is thrown away */
234 * Ensure (sub)transaction stack entry for the given nest_level exists, adding
243 if (xact_state == NULL || xact_state->
nest_level != nest_level)
251 xact_state->
first = NULL;
258 * Get stat items that need to be dropped at commit / abort.
260 * When committing, stats for objects that have been dropped in the
261 * transaction are returned. When aborting, stats for newly created objects are
264 * Used by COMMIT / ABORT and 2PC PREPARE processing when building their
265 * respective WAL records, to ensure stats are dropped in case of a crash / on
268 * The list of items is allocated in CurrentMemoryContext and must be freed by
269 * the caller (directly or via memory context reset).
278 if (xact_state == NULL)
282 * We expect to be called for subtransaction abort (which logs a WAL
283 * record), but not for subtransaction commit (which doesn't).
286 Assert(!isCommit || xact_state->
prev == NULL);
309 * Execute scheduled drops post-commit. Called from xact_redo_commit() /
310 * xact_redo_abort() during recovery, and from FinishPreparedTransaction()
311 * during normal 2PC COMMIT/ABORT PREPARED processing.
316 int not_freed_count = 0;
321 for (
int i = 0;
i < ndrops;
i++)
330 if (not_freed_count > 0)
354 * Create a stats entry for a newly created database object in a transactional
357 * I.e. if the current (sub-)transaction aborts, the stats entry will also be
366 errmsg(
"resetting existing statistics for kind %s, db=%u, oid=%" PRIu64,
377 * Drop a stats entry for a just dropped database object in a transactional
380 * I.e. if the current (sub-)transaction aborts, the stats entry will stay
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
#define dclist_container(type, membername, ptr)
static void dclist_push_tail(dclist_head *head, dlist_node *node)
static uint32 dclist_count(const dclist_head *head)
static void dclist_delete_from(dclist_head *head, dlist_node *node)
static void dclist_init(dclist_head *head)
#define dclist_foreach_modify(iter, lhead)
#define dclist_foreach(iter, lhead)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext TopTransactionContext
void pfree(void *pointer)
void pgstat_reset(PgStat_Kind kind, Oid dboid, uint64 objid)
const PgStat_KindInfo * pgstat_get_kind_info(PgStat_Kind kind)
void pgstat_clear_snapshot(void)
void AtEOXact_PgStat_Database(bool isCommit, bool parallel)
void AtPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
void AtEOXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit)
void PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state)
void AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
void pgstat_request_entry_refs_gc(void)
PgStat_EntryRef * pgstat_get_entry_ref(PgStat_Kind kind, Oid dboid, uint64 objid, bool create, bool *created_entry)
bool pgstat_drop_entry(PgStat_Kind kind, Oid dboid, uint64 objid)
static PgStat_SubXactStatus * pgStatXactStack
void AtPrepare_PgStat(void)
void pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items, bool is_redo)
void AtEOXact_PgStat(bool isCommit, bool parallel)
static void AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit, int nestDepth)
void pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, uint64 objid)
void pgstat_create_transactional(PgStat_Kind kind, Oid dboid, uint64 objid)
struct PgStat_PendingDroppedStatsItem PgStat_PendingDroppedStatsItem
void PostPrepare_PgStat(void)
PgStat_SubXactStatus * pgstat_get_xact_stack_level(int nest_level)
static void create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, uint64 objid, bool is_create)
int pgstat_get_transactional_drops(bool isCommit, xl_xact_stats_item **items)
void AtEOSubXact_PgStat(bool isCommit, int nestDepth)
static void AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
PgStat_TableXactStatus * first
struct PgStat_SubXactStatus * prev
dclist_head pending_drops
int GetCurrentTransactionNestLevel(void)