LCOV - differential code coverage report
Current view: top level - src/backend/utils/activity - pgstat_xact.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage 16@8cea358b128 vs 17@8cea358b128 Lines: 96.2 % 131 126 5 126
Current Date: 2024-04-14 14:21:10 Functions: 100.0 % 12 12 12
Baseline: 16@8cea358b128 Branches: 81.0 % 100 81 19 81
Baseline Date: 2024-04-14 14:21:09 Line coverage date bins:
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed (240..) days: 96.2 % 131 126 5 126
Function coverage date bins:
(240..) days: 100.0 % 12 12 12
Branch coverage date bins:
(240..) days: 81.0 % 100 81 19 81

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /* -------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * pgstat_xact.c
                                  4                 :                :  *    Transactional integration for the cumulative statistics system.
                                  5                 :                :  *
                                  6                 :                :  * Copyright (c) 2001-2024, PostgreSQL Global Development Group
                                  7                 :                :  *
                                  8                 :                :  * IDENTIFICATION
                                  9                 :                :  *    src/backend/utils/activity/pgstat_xact.c
                                 10                 :                :  * -------------------------------------------------------------------------
                                 11                 :                :  */
                                 12                 :                : 
                                 13                 :                : #include "postgres.h"
                                 14                 :                : 
                                 15                 :                : #include "access/xact.h"
                                 16                 :                : #include "pgstat.h"
                                 17                 :                : #include "utils/memutils.h"
                                 18                 :                : #include "utils/pgstat_internal.h"
                                 19                 :                : 
                                 20                 :                : 
                                 21                 :                : typedef struct PgStat_PendingDroppedStatsItem
                                 22                 :                : {
                                 23                 :                :     xl_xact_stats_item item;
                                 24                 :                :     bool        is_create;
                                 25                 :                :     dlist_node  node;
                                 26                 :                : } PgStat_PendingDroppedStatsItem;
                                 27                 :                : 
                                 28                 :                : 
                                 29                 :                : static void AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit);
                                 30                 :                : static void AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state,
                                 31                 :                :                                             bool isCommit, int nestDepth);
                                 32                 :                : 
                                 33                 :                : static PgStat_SubXactStatus *pgStatXactStack = NULL;
                                 34                 :                : 
                                 35                 :                : 
                                 36                 :                : /*
                                 37                 :                :  * Called from access/transam/xact.c at top-level transaction commit/abort.
                                 38                 :                :  */
                                 39                 :                : void
  739 andres@anarazel.de         40                 :CBC      432923 : AtEOXact_PgStat(bool isCommit, bool parallel)
                                 41                 :                : {
                                 42                 :                :     PgStat_SubXactStatus *xact_state;
                                 43                 :                : 
                                 44                 :         432923 :     AtEOXact_PgStat_Database(isCommit, parallel);
                                 45                 :                : 
                                 46                 :                :     /* handle transactional stats information */
                                 47                 :         432923 :     xact_state = pgStatXactStack;
                                 48         [ +  + ]:         432923 :     if (xact_state != NULL)
                                 49                 :                :     {
                                 50         [ -  + ]:         110118 :         Assert(xact_state->nest_level == 1);
                                 51         [ -  + ]:         110118 :         Assert(xact_state->prev == NULL);
                                 52                 :                : 
                                 53                 :         110118 :         AtEOXact_PgStat_Relations(xact_state, isCommit);
                                 54                 :         110118 :         AtEOXact_PgStat_DroppedStats(xact_state, isCommit);
                                 55                 :                :     }
                                 56                 :         432923 :     pgStatXactStack = NULL;
                                 57                 :                : 
                                 58                 :                :     /* Make sure any stats snapshot is thrown away */
                                 59                 :         432923 :     pgstat_clear_snapshot();
                                 60                 :         432923 : }
                                 61                 :                : 
                                 62                 :                : /*
                                 63                 :                :  * When committing, drop stats for objects dropped in the transaction. When
                                 64                 :                :  * aborting, drop stats for objects created in the transaction.
                                 65                 :                :  */
                                 66                 :                : static void
                                 67                 :         110118 : AtEOXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state, bool isCommit)
                                 68                 :                : {
                                 69                 :                :     dlist_mutable_iter iter;
                                 70                 :         110118 :     int         not_freed_count = 0;
                                 71                 :                : 
  529 drowley@postgresql.o       72         [ +  + ]:         110118 :     if (dclist_count(&xact_state->pending_drops) == 0)
  739 andres@anarazel.de         73                 :          71383 :         return;
                                 74                 :                : 
  529 drowley@postgresql.o       75   [ +  -  +  + ]:         140503 :     dclist_foreach_modify(iter, &xact_state->pending_drops)
                                 76                 :                :     {
  739 andres@anarazel.de         77                 :         101768 :         PgStat_PendingDroppedStatsItem *pending =
  331 tgl@sss.pgh.pa.us          78                 :         101768 :             dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur);
  739 andres@anarazel.de         79                 :         101768 :         xl_xact_stats_item *it = &pending->item;
                                 80                 :                : 
                                 81   [ +  +  +  + ]:         101768 :         if (isCommit && !pending->is_create)
                                 82                 :                :         {
                                 83                 :                :             /*
                                 84                 :                :              * Transaction that dropped an object committed. Drop the stats
                                 85                 :                :              * too.
                                 86                 :                :              */
                                 87         [ +  + ]:          40117 :             if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
                                 88                 :           4813 :                 not_freed_count++;
                                 89                 :                :         }
                                 90   [ +  +  +  + ]:          66464 :         else if (!isCommit && pending->is_create)
                                 91                 :                :         {
                                 92                 :                :             /*
                                 93                 :                :              * Transaction that created an object aborted. Drop the stats
                                 94                 :                :              * associated with the object.
                                 95                 :                :              */
                                 96         [ -  + ]:           2058 :             if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
  739 andres@anarazel.de         97                 :UBC           0 :                 not_freed_count++;
                                 98                 :                :         }
                                 99                 :                : 
  529 drowley@postgresql.o      100                 :CBC      101768 :         dclist_delete_from(&xact_state->pending_drops, &pending->node);
  739 andres@anarazel.de        101                 :         101768 :         pfree(pending);
                                102                 :                :     }
                                103                 :                : 
                                104         [ +  + ]:          38735 :     if (not_freed_count > 0)
                                105                 :           1827 :         pgstat_request_entry_refs_gc();
                                106                 :                : }
                                107                 :                : 
                                108                 :                : /*
                                109                 :                :  * Called from access/transam/xact.c at subtransaction commit/abort.
                                110                 :                :  */
                                111                 :                : void
                                112                 :           9927 : AtEOSubXact_PgStat(bool isCommit, int nestDepth)
                                113                 :                : {
                                114                 :                :     PgStat_SubXactStatus *xact_state;
                                115                 :                : 
                                116                 :                :     /* merge the sub-transaction's transactional stats into the parent */
                                117                 :           9927 :     xact_state = pgStatXactStack;
                                118         [ +  + ]:           9927 :     if (xact_state != NULL &&
                                119         [ +  + ]:           4677 :         xact_state->nest_level >= nestDepth)
                                120                 :                :     {
                                121                 :                :         /* delink xact_state from stack immediately to simplify reuse case */
                                122                 :           4248 :         pgStatXactStack = xact_state->prev;
                                123                 :                : 
                                124                 :           4248 :         AtEOSubXact_PgStat_Relations(xact_state, isCommit, nestDepth);
                                125                 :           4248 :         AtEOSubXact_PgStat_DroppedStats(xact_state, isCommit, nestDepth);
                                126                 :                : 
                                127                 :           4248 :         pfree(xact_state);
                                128                 :                :     }
                                129                 :           9927 : }
                                130                 :                : 
                                131                 :                : /*
                                132                 :                :  * Like AtEOXact_PgStat_DroppedStats(), but for subtransactions.
                                133                 :                :  */
                                134                 :                : static void
                                135                 :           4248 : AtEOSubXact_PgStat_DroppedStats(PgStat_SubXactStatus *xact_state,
                                136                 :                :                                 bool isCommit, int nestDepth)
                                137                 :                : {
                                138                 :                :     PgStat_SubXactStatus *parent_xact_state;
                                139                 :                :     dlist_mutable_iter iter;
                                140                 :           4248 :     int         not_freed_count = 0;
                                141                 :                : 
  529 drowley@postgresql.o      142         [ +  + ]:           4248 :     if (dclist_count(&xact_state->pending_drops) == 0)
  739 andres@anarazel.de        143                 :           4176 :         return;
                                144                 :                : 
                                145                 :             72 :     parent_xact_state = pgstat_get_xact_stack_level(nestDepth - 1);
                                146                 :                : 
  529 drowley@postgresql.o      147   [ +  -  +  + ]:            211 :     dclist_foreach_modify(iter, &xact_state->pending_drops)
                                148                 :                :     {
  739 andres@anarazel.de        149                 :            139 :         PgStat_PendingDroppedStatsItem *pending =
  331 tgl@sss.pgh.pa.us         150                 :            139 :             dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur);
  739 andres@anarazel.de        151                 :            139 :         xl_xact_stats_item *it = &pending->item;
                                152                 :                : 
  529 drowley@postgresql.o      153                 :            139 :         dclist_delete_from(&xact_state->pending_drops, &pending->node);
                                154                 :                : 
  739 andres@anarazel.de        155   [ +  +  +  + ]:            139 :         if (!isCommit && pending->is_create)
                                156                 :                :         {
                                157                 :                :             /*
                                158                 :                :              * Subtransaction creating a new stats object aborted. Drop the
                                159                 :                :              * stats object.
                                160                 :                :              */
                                161         [ -  + ]:             69 :             if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
  739 andres@anarazel.de        162                 :UBC           0 :                 not_freed_count++;
  739 andres@anarazel.de        163                 :CBC          69 :             pfree(pending);
                                164                 :                :         }
                                165         [ +  + ]:             70 :         else if (isCommit)
                                166                 :                :         {
                                167                 :                :             /*
                                168                 :                :              * Subtransaction dropping a stats object committed. Can't yet
                                169                 :                :              * remove the stats object, the surrounding transaction might
                                170                 :                :              * still abort. Pass it on to the parent.
                                171                 :                :              */
  529 drowley@postgresql.o      172                 :             49 :             dclist_push_tail(&parent_xact_state->pending_drops, &pending->node);
                                173                 :                :         }
                                174                 :                :         else
                                175                 :                :         {
  739 andres@anarazel.de        176                 :             21 :             pfree(pending);
                                177                 :                :         }
                                178                 :                :     }
                                179                 :                : 
  529 drowley@postgresql.o      180         [ -  + ]:             72 :     Assert(dclist_count(&xact_state->pending_drops) == 0);
  739 andres@anarazel.de        181         [ -  + ]:             72 :     if (not_freed_count > 0)
  739 andres@anarazel.de        182                 :UBC           0 :         pgstat_request_entry_refs_gc();
                                183                 :                : }
                                184                 :                : 
                                185                 :                : /*
                                186                 :                :  * Save the transactional stats state at 2PC transaction prepare.
                                187                 :                :  */
                                188                 :                : void
  739 andres@anarazel.de        189                 :CBC         391 : AtPrepare_PgStat(void)
                                190                 :                : {
                                191                 :                :     PgStat_SubXactStatus *xact_state;
                                192                 :                : 
                                193                 :            391 :     xact_state = pgStatXactStack;
                                194         [ +  + ]:            391 :     if (xact_state != NULL)
                                195                 :                :     {
                                196         [ -  + ]:            384 :         Assert(xact_state->nest_level == 1);
                                197         [ -  + ]:            384 :         Assert(xact_state->prev == NULL);
                                198                 :                : 
                                199                 :            384 :         AtPrepare_PgStat_Relations(xact_state);
                                200                 :                :     }
                                201                 :            391 : }
                                202                 :                : 
                                203                 :                : /*
                                204                 :                :  * Clean up after successful PREPARE.
                                205                 :                :  *
                                206                 :                :  * Note: AtEOXact_PgStat is not called during PREPARE.
                                207                 :                :  */
                                208                 :                : void
                                209                 :            391 : PostPrepare_PgStat(void)
                                210                 :                : {
                                211                 :                :     PgStat_SubXactStatus *xact_state;
                                212                 :                : 
                                213                 :                :     /*
                                214                 :                :      * We don't bother to free any of the transactional state, since it's all
                                215                 :                :      * in TopTransactionContext and will go away anyway.
                                216                 :                :      */
                                217                 :            391 :     xact_state = pgStatXactStack;
                                218         [ +  + ]:            391 :     if (xact_state != NULL)
                                219                 :                :     {
                                220         [ -  + ]:            384 :         Assert(xact_state->nest_level == 1);
                                221         [ -  + ]:            384 :         Assert(xact_state->prev == NULL);
                                222                 :                : 
                                223                 :            384 :         PostPrepare_PgStat_Relations(xact_state);
                                224                 :                :     }
                                225                 :            391 :     pgStatXactStack = NULL;
                                226                 :                : 
                                227                 :                :     /* Make sure any stats snapshot is thrown away */
                                228                 :            391 :     pgstat_clear_snapshot();
                                229                 :            391 : }
                                230                 :                : 
                                231                 :                : /*
                                232                 :                :  * Ensure (sub)transaction stack entry for the given nest_level exists, adding
                                233                 :                :  * it if needed.
                                234                 :                :  */
                                235                 :                : PgStat_SubXactStatus *
                                236                 :         410055 : pgstat_get_xact_stack_level(int nest_level)
                                237                 :                : {
                                238                 :                :     PgStat_SubXactStatus *xact_state;
                                239                 :                : 
                                240                 :         410055 :     xact_state = pgStatXactStack;
                                241   [ +  +  +  + ]:         410055 :     if (xact_state == NULL || xact_state->nest_level != nest_level)
                                242                 :                :     {
                                243                 :                :         xact_state = (PgStat_SubXactStatus *)
                                244                 :         114755 :             MemoryContextAlloc(TopTransactionContext,
                                245                 :                :                                sizeof(PgStat_SubXactStatus));
  529 drowley@postgresql.o      246                 :         114755 :         dclist_init(&xact_state->pending_drops);
  739 andres@anarazel.de        247                 :         114755 :         xact_state->nest_level = nest_level;
                                248                 :         114755 :         xact_state->prev = pgStatXactStack;
                                249                 :         114755 :         xact_state->first = NULL;
                                250                 :         114755 :         pgStatXactStack = xact_state;
                                251                 :                :     }
                                252                 :         410055 :     return xact_state;
                                253                 :                : }
                                254                 :                : 
                                255                 :                : /*
                                256                 :                :  * Get stat items that need to be dropped at commit / abort.
                                257                 :                :  *
                                258                 :                :  * When committing, stats for objects that have been dropped in the
                                259                 :                :  * transaction are returned. When aborting, stats for newly created objects are
                                260                 :                :  * returned.
                                261                 :                :  *
                                262                 :                :  * Used by COMMIT / ABORT and 2PC PREPARE processing when building their
                                263                 :                :  * respective WAL records, to ensure stats are dropped in case of a crash / on
                                264                 :                :  * standbys.
                                265                 :                :  *
                                266                 :                :  * The list of items is allocated in CurrentMemoryContext and must be freed by
                                267                 :                :  * the caller (directly or via memory context reset).
                                268                 :                :  */
                                269                 :                : int
                                270                 :         414534 : pgstat_get_transactional_drops(bool isCommit, xl_xact_stats_item **items)
                                271                 :                : {
                                272                 :         414534 :     PgStat_SubXactStatus *xact_state = pgStatXactStack;
                                273                 :         414534 :     int         nitems = 0;
                                274                 :                :     dlist_iter  iter;
                                275                 :                : 
                                276         [ +  + ]:         414534 :     if (xact_state == NULL)
                                277                 :         303006 :         return 0;
                                278                 :                : 
                                279                 :                :     /*
                                280                 :                :      * We expect to be called for subtransaction abort (which logs a WAL
                                281                 :                :      * record), but not for subtransaction commit (which doesn't).
                                282                 :                :      */
                                283   [ +  +  -  + ]:         111528 :     Assert(!isCommit || xact_state->nest_level == 1);
                                284   [ +  +  -  + ]:         111528 :     Assert(!isCommit || xact_state->prev == NULL);
                                285                 :                : 
  529 drowley@postgresql.o      286                 :         111528 :     *items = palloc(dclist_count(&xact_state->pending_drops)
                                287                 :                :                     * sizeof(xl_xact_stats_item));
                                288                 :                : 
                                289   [ +  -  +  + ]:         214107 :     dclist_foreach(iter, &xact_state->pending_drops)
                                290                 :                :     {
  739 andres@anarazel.de        291                 :         102579 :         PgStat_PendingDroppedStatsItem *pending =
  331 tgl@sss.pgh.pa.us         292                 :         102579 :             dclist_container(PgStat_PendingDroppedStatsItem, node, iter.cur);
                                293                 :                : 
  739 andres@anarazel.de        294   [ +  +  +  + ]:         102579 :         if (isCommit && pending->is_create)
                                295                 :          64026 :             continue;
                                296   [ +  +  +  + ]:          38553 :         if (!isCommit && !pending->is_create)
                                297                 :            442 :             continue;
                                298                 :                : 
  529 drowley@postgresql.o      299         [ -  + ]:          38111 :         Assert(nitems < dclist_count(&xact_state->pending_drops));
  739 andres@anarazel.de        300                 :          38111 :         (*items)[nitems++] = pending->item;
                                301                 :                :     }
                                302                 :                : 
                                303                 :         111528 :     return nitems;
                                304                 :                : }
                                305                 :                : 
                                306                 :                : /*
                                307                 :                :  * Execute scheduled drops post-commit. Called from xact_redo_commit() /
                                308                 :                :  * xact_redo_abort() during recovery, and from FinishPreparedTransaction()
                                309                 :                :  * during normal 2PC COMMIT/ABORT PREPARED processing.
                                310                 :                :  */
                                311                 :                : void
                                312                 :           3196 : pgstat_execute_transactional_drops(int ndrops, struct xl_xact_stats_item *items, bool is_redo)
                                313                 :                : {
                                314                 :           3196 :     int         not_freed_count = 0;
                                315                 :                : 
                                316         [ +  + ]:           3196 :     if (ndrops == 0)
                                317                 :            388 :         return;
                                318                 :                : 
                                319         [ +  + ]:          11488 :     for (int i = 0; i < ndrops; i++)
                                320                 :                :     {
                                321                 :           8680 :         xl_xact_stats_item *it = &items[i];
                                322                 :                : 
                                323         [ +  + ]:           8680 :         if (!pgstat_drop_entry(it->kind, it->dboid, it->objoid))
                                324                 :              2 :             not_freed_count++;
                                325                 :                :     }
                                326                 :                : 
                                327         [ +  + ]:           2808 :     if (not_freed_count > 0)
                                328                 :              2 :         pgstat_request_entry_refs_gc();
                                329                 :                : }
                                330                 :                : 
                                331                 :                : static void
                                332                 :         101901 : create_drop_transactional_internal(PgStat_Kind kind, Oid dboid, Oid objoid, bool is_create)
                                333                 :                : {
                                334                 :         101901 :     int         nest_level = GetCurrentTransactionNestLevel();
                                335                 :                :     PgStat_SubXactStatus *xact_state;
                                336                 :                :     PgStat_PendingDroppedStatsItem *drop = (PgStat_PendingDroppedStatsItem *)
  331 tgl@sss.pgh.pa.us         337                 :         101901 :         MemoryContextAlloc(TopTransactionContext, sizeof(PgStat_PendingDroppedStatsItem));
                                338                 :                : 
  739 andres@anarazel.de        339                 :         101901 :     xact_state = pgstat_get_xact_stack_level(nest_level);
                                340                 :                : 
                                341                 :         101901 :     drop->is_create = is_create;
                                342                 :         101901 :     drop->item.kind = kind;
                                343                 :         101901 :     drop->item.dboid = dboid;
                                344                 :         101901 :     drop->item.objoid = objoid;
                                345                 :                : 
  529 drowley@postgresql.o      346                 :         101901 :     dclist_push_tail(&xact_state->pending_drops, &drop->node);
  739 andres@anarazel.de        347                 :         101901 : }
                                348                 :                : 
                                349                 :                : /*
                                350                 :                :  * Create a stats entry for a newly created database object in a transactional
                                351                 :                :  * manner.
                                352                 :                :  *
                                353                 :                :  * I.e. if the current (sub-)transaction aborts, the stats entry will also be
                                354                 :                :  * dropped.
                                355                 :                :  */
                                356                 :                : void
                                357                 :          66153 : pgstat_create_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
                                358                 :                : {
                                359         [ -  + ]:          66153 :     if (pgstat_get_entry_ref(kind, dboid, objoid, false, NULL))
                                360                 :                :     {
  739 andres@anarazel.de        361         [ #  # ]:UBC           0 :         ereport(WARNING,
                                362                 :                :                 errmsg("resetting existing statistics for kind %s, db=%u, oid=%u",
                                363                 :                :                        (pgstat_get_kind_info(kind))->name, dboid, objoid));
                                364                 :                : 
                                365                 :              0 :         pgstat_reset(kind, dboid, objoid);
                                366                 :                :     }
                                367                 :                : 
  739 andres@anarazel.de        368                 :CBC       66153 :     create_drop_transactional_internal(kind, dboid, objoid, /* create */ true);
                                369                 :          66153 : }
                                370                 :                : 
                                371                 :                : /*
                                372                 :                :  * Drop a stats entry for a just dropped database object in a transactional
                                373                 :                :  * manner.
                                374                 :                :  *
                                375                 :                :  * I.e. if the current (sub-)transaction aborts, the stats entry will stay
                                376                 :                :  * alive.
                                377                 :                :  */
                                378                 :                : void
                                379                 :          35748 : pgstat_drop_transactional(PgStat_Kind kind, Oid dboid, Oid objoid)
                                380                 :                : {
                                381                 :          35748 :     create_drop_transactional_internal(kind, dboid, objoid, /* create */ false);
                                382                 :          35748 : }
        

Generated by: LCOV version 2.1-beta2-3-g6141622