LCOV - code coverage report
Current view: top level - src/test/modules/injection_points - injection_stats.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 42 47 89.4 %
Date: 2025-01-18 04:15:08 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*--------------------------------------------------------------------------
       2             :  *
       3             :  * injection_stats.c
       4             :  *      Code for statistics of injection points.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *      src/test/modules/injection_points/injection_stats.c
      11             :  *
      12             :  * -------------------------------------------------------------------------
      13             :  */
      14             : 
      15             : #include "postgres.h"
      16             : 
      17             : #include "fmgr.h"
      18             : 
      19             : #include "common/hashfn.h"
      20             : #include "injection_stats.h"
      21             : #include "pgstat.h"
      22             : #include "utils/builtins.h"
      23             : #include "utils/pgstat_internal.h"
      24             : 
      25             : /* Structures for statistics of injection points */
      26             : typedef struct PgStat_StatInjEntry
      27             : {
      28             :     PgStat_Counter numcalls;    /* number of times point has been run */
      29             : } PgStat_StatInjEntry;
      30             : 
      31             : typedef struct PgStatShared_InjectionPoint
      32             : {
      33             :     PgStatShared_Common header;
      34             :     PgStat_StatInjEntry stats;
      35             : } PgStatShared_InjectionPoint;
      36             : 
      37             : static bool injection_stats_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
      38             : 
      39             : static const PgStat_KindInfo injection_stats = {
      40             :     .name = "injection_points",
      41             :     .fixed_amount = false,      /* Bounded by the number of points */
      42             :     .write_to_file = true,
      43             : 
      44             :     /* Injection points are system-wide */
      45             :     .accessed_across_databases = true,
      46             : 
      47             :     .shared_size = sizeof(PgStatShared_InjectionPoint),
      48             :     .shared_data_off = offsetof(PgStatShared_InjectionPoint, stats),
      49             :     .shared_data_len = sizeof(((PgStatShared_InjectionPoint *) 0)->stats),
      50             :     .pending_size = sizeof(PgStat_StatInjEntry),
      51             :     .flush_pending_cb = injection_stats_flush_cb,
      52             : };
      53             : 
      54             : /*
      55             :  * Compute stats entry idx from point name with an 8-byte hash.
      56             :  */
      57             : #define PGSTAT_INJ_IDX(name) hash_bytes_extended((const unsigned char *) name, strlen(name), 0)
      58             : 
      59             : /*
      60             :  * Kind ID reserved for statistics of injection points.
      61             :  */
      62             : #define PGSTAT_KIND_INJECTION   129
      63             : 
      64             : /* Track if stats are loaded */
      65             : static bool inj_stats_loaded = false;
      66             : 
      67             : /*
      68             :  * Callback for stats handling
      69             :  */
      70             : static bool
      71           8 : injection_stats_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
      72             : {
      73             :     PgStat_StatInjEntry *localent;
      74             :     PgStatShared_InjectionPoint *shfuncent;
      75             : 
      76           8 :     localent = (PgStat_StatInjEntry *) entry_ref->pending;
      77           8 :     shfuncent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats;
      78             : 
      79           8 :     if (!pgstat_lock_entry(entry_ref, nowait))
      80           0 :         return false;
      81             : 
      82           8 :     shfuncent->stats.numcalls += localent->numcalls;
      83             : 
      84           8 :     pgstat_unlock_entry(entry_ref);
      85             : 
      86           8 :     return true;
      87             : }
      88             : 
      89             : /*
      90             :  * Support function for the SQL-callable pgstat* functions.  Returns
      91             :  * a pointer to the injection point statistics struct.
      92             :  */
      93             : static PgStat_StatInjEntry *
      94           6 : pgstat_fetch_stat_injentry(const char *name)
      95             : {
      96           6 :     PgStat_StatInjEntry *entry = NULL;
      97             : 
      98           6 :     if (!inj_stats_loaded || !inj_stats_enabled)
      99           0 :         return NULL;
     100             : 
     101             :     /* Compile the lookup key as a hash of the point name */
     102           6 :     entry = (PgStat_StatInjEntry *) pgstat_fetch_entry(PGSTAT_KIND_INJECTION,
     103             :                                                        InvalidOid,
     104           6 :                                                        PGSTAT_INJ_IDX(name));
     105           6 :     return entry;
     106             : }
     107             : 
     108             : /*
     109             :  * Workhorse to do the registration work, called in _PG_init().
     110             :  */
     111             : void
     112           8 : pgstat_register_inj(void)
     113             : {
     114           8 :     pgstat_register_kind(PGSTAT_KIND_INJECTION, &injection_stats);
     115             : 
     116             :     /* mark stats as loaded */
     117           8 :     inj_stats_loaded = true;
     118           8 : }
     119             : 
     120             : /*
     121             :  * Report injection point creation.
     122             :  */
     123             : void
     124          70 : pgstat_create_inj(const char *name)
     125             : {
     126             :     PgStat_EntryRef *entry_ref;
     127             :     PgStatShared_InjectionPoint *shstatent;
     128             : 
     129             :     /* leave if disabled */
     130          70 :     if (!inj_stats_loaded || !inj_stats_enabled)
     131          68 :         return;
     132             : 
     133           2 :     entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_INJECTION, InvalidOid,
     134           2 :                                           PGSTAT_INJ_IDX(name), NULL);
     135             : 
     136           2 :     shstatent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats;
     137             : 
     138             :     /* initialize shared memory data */
     139           2 :     memset(&shstatent->stats, 0, sizeof(shstatent->stats));
     140             : }
     141             : 
     142             : /*
     143             :  * Report injection point drop.
     144             :  */
     145             : void
     146         158 : pgstat_drop_inj(const char *name)
     147             : {
     148             :     /* leave if disabled */
     149         158 :     if (!inj_stats_loaded || !inj_stats_enabled)
     150         158 :         return;
     151             : 
     152           0 :     if (!pgstat_drop_entry(PGSTAT_KIND_INJECTION, InvalidOid,
     153           0 :                            PGSTAT_INJ_IDX(name)))
     154           0 :         pgstat_request_entry_refs_gc();
     155             : }
     156             : 
     157             : /*
     158             :  * Report statistics for injection point.
     159             :  *
     160             :  * This is simple because the set of stats to report currently is simple:
     161             :  * track the number of times a point has been run.
     162             :  */
     163             : void
     164          82 : pgstat_report_inj(const char *name)
     165             : {
     166             :     PgStat_EntryRef *entry_ref;
     167             :     PgStatShared_InjectionPoint *shstatent;
     168             :     PgStat_StatInjEntry *statent;
     169             : 
     170             :     /* leave if disabled */
     171          82 :     if (!inj_stats_loaded || !inj_stats_enabled)
     172          76 :         return;
     173             : 
     174           6 :     entry_ref = pgstat_prep_pending_entry(PGSTAT_KIND_INJECTION, InvalidOid,
     175           6 :                                           PGSTAT_INJ_IDX(name), NULL);
     176             : 
     177           6 :     shstatent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats;
     178           6 :     statent = &shstatent->stats;
     179             : 
     180             :     /* Update the injection point statistics */
     181           6 :     statent->numcalls++;
     182             : }
     183             : 
     184             : /*
     185             :  * SQL function returning the number of times an injection point
     186             :  * has been called.
     187             :  */
     188          46 : PG_FUNCTION_INFO_V1(injection_points_stats_numcalls);
     189             : Datum
     190           6 : injection_points_stats_numcalls(PG_FUNCTION_ARGS)
     191             : {
     192           6 :     char       *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
     193           6 :     PgStat_StatInjEntry *entry = pgstat_fetch_stat_injentry(name);
     194             : 
     195           6 :     if (entry == NULL)
     196           2 :         PG_RETURN_NULL();
     197             : 
     198           4 :     PG_RETURN_INT64(entry->numcalls);
     199             : }

Generated by: LCOV version 1.14