LCOV - differential code coverage report
Current view: top level - src/backend/utils/activity - pgstat_xact.c (source / functions) Coverage Total Hit LBC UIC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 96.2 % 131 126 2 3 2 65 16 43 3 72 9
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 12 12 10 1 1 10
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (120,180] days: 100.0 % 16 16 16
Legend: Lines: hit not hit (240..) days: 95.7 % 115 110 2 3 2 65 43 3 72
Function coverage date bins:
(240..) days: 54.5 % 22 12 10 1 1 10

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

Generated by: LCOV version v1.16-55-g56c0a2a