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: 37 48 77.1 %
Date: 2024-11-21 08:14:44 Functions: 7 8 87.5 %
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-2024, 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             : 
      43             :     /* Injection points are system-wide */
      44             :     .accessed_across_databases = true,
      45             : 
      46             :     .shared_size = sizeof(PgStatShared_InjectionPoint),
      47             :     .shared_data_off = offsetof(PgStatShared_InjectionPoint, stats),
      48             :     .shared_data_len = sizeof(((PgStatShared_InjectionPoint *) 0)->stats),
      49             :     .pending_size = sizeof(PgStat_StatInjEntry),
      50             :     .flush_pending_cb = injection_stats_flush_cb,
      51             : };
      52             : 
      53             : /*
      54             :  * Compute stats entry idx from point name with an 8-byte hash.
      55             :  */
      56             : #define PGSTAT_INJ_IDX(name) hash_bytes_extended((const unsigned char *) name, strlen(name), 0)
      57             : 
      58             : /*
      59             :  * Kind ID reserved for statistics of injection points.
      60             :  */
      61             : #define PGSTAT_KIND_INJECTION   129
      62             : 
      63             : /* Track if stats are loaded */
      64             : static bool inj_stats_loaded = false;
      65             : 
      66             : /*
      67             :  * Callback for stats handling
      68             :  */
      69             : static bool
      70           0 : injection_stats_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
      71             : {
      72             :     PgStat_StatInjEntry *localent;
      73             :     PgStatShared_InjectionPoint *shfuncent;
      74             : 
      75           0 :     localent = (PgStat_StatInjEntry *) entry_ref->pending;
      76           0 :     shfuncent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats;
      77             : 
      78           0 :     if (!pgstat_lock_entry(entry_ref, nowait))
      79           0 :         return false;
      80             : 
      81           0 :     shfuncent->stats.numcalls += localent->numcalls;
      82           0 :     return true;
      83             : }
      84             : 
      85             : /*
      86             :  * Support function for the SQL-callable pgstat* functions.  Returns
      87             :  * a pointer to the injection point statistics struct.
      88             :  */
      89             : static PgStat_StatInjEntry *
      90           6 : pgstat_fetch_stat_injentry(const char *name)
      91             : {
      92           6 :     PgStat_StatInjEntry *entry = NULL;
      93             : 
      94           6 :     if (!inj_stats_loaded || !inj_stats_enabled)
      95           0 :         return NULL;
      96             : 
      97             :     /* Compile the lookup key as a hash of the point name */
      98           6 :     entry = (PgStat_StatInjEntry *) pgstat_fetch_entry(PGSTAT_KIND_INJECTION,
      99             :                                                        InvalidOid,
     100           6 :                                                        PGSTAT_INJ_IDX(name));
     101           6 :     return entry;
     102             : }
     103             : 
     104             : /*
     105             :  * Workhorse to do the registration work, called in _PG_init().
     106             :  */
     107             : void
     108           8 : pgstat_register_inj(void)
     109             : {
     110           8 :     pgstat_register_kind(PGSTAT_KIND_INJECTION, &injection_stats);
     111             : 
     112             :     /* mark stats as loaded */
     113           8 :     inj_stats_loaded = true;
     114           8 : }
     115             : 
     116             : /*
     117             :  * Report injection point creation.
     118             :  */
     119             : void
     120          70 : pgstat_create_inj(const char *name)
     121             : {
     122             :     PgStat_EntryRef *entry_ref;
     123             :     PgStatShared_InjectionPoint *shstatent;
     124             : 
     125             :     /* leave if disabled */
     126          70 :     if (!inj_stats_loaded || !inj_stats_enabled)
     127          68 :         return;
     128             : 
     129           2 :     entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_INJECTION, InvalidOid,
     130           2 :                                             PGSTAT_INJ_IDX(name), false);
     131           2 :     shstatent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats;
     132             : 
     133             :     /* initialize shared memory data */
     134           2 :     memset(&shstatent->stats, 0, sizeof(shstatent->stats));
     135           2 :     pgstat_unlock_entry(entry_ref);
     136             : }
     137             : 
     138             : /*
     139             :  * Report injection point drop.
     140             :  */
     141             : void
     142         158 : pgstat_drop_inj(const char *name)
     143             : {
     144             :     /* leave if disabled */
     145         158 :     if (!inj_stats_loaded || !inj_stats_enabled)
     146         158 :         return;
     147             : 
     148           0 :     if (!pgstat_drop_entry(PGSTAT_KIND_INJECTION, InvalidOid,
     149           0 :                            PGSTAT_INJ_IDX(name)))
     150           0 :         pgstat_request_entry_refs_gc();
     151             : }
     152             : 
     153             : /*
     154             :  * Report statistics for injection point.
     155             :  *
     156             :  * This is simple because the set of stats to report currently is simple:
     157             :  * track the number of times a point has been run.
     158             :  */
     159             : void
     160          84 : pgstat_report_inj(const char *name)
     161             : {
     162             :     PgStat_EntryRef *entry_ref;
     163             :     PgStatShared_InjectionPoint *shstatent;
     164             :     PgStat_StatInjEntry *statent;
     165             : 
     166             :     /* leave if disabled */
     167          84 :     if (!inj_stats_loaded || !inj_stats_enabled)
     168          78 :         return;
     169             : 
     170           6 :     entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_INJECTION, InvalidOid,
     171           6 :                                             PGSTAT_INJ_IDX(name), false);
     172             : 
     173           6 :     shstatent = (PgStatShared_InjectionPoint *) entry_ref->shared_stats;
     174           6 :     statent = &shstatent->stats;
     175             : 
     176             :     /* Update the injection point statistics */
     177           6 :     statent->numcalls++;
     178             : 
     179           6 :     pgstat_unlock_entry(entry_ref);
     180             : }
     181             : 
     182             : /*
     183             :  * SQL function returning the number of times an injection point
     184             :  * has been called.
     185             :  */
     186          44 : PG_FUNCTION_INFO_V1(injection_points_stats_numcalls);
     187             : Datum
     188           6 : injection_points_stats_numcalls(PG_FUNCTION_ARGS)
     189             : {
     190           6 :     char       *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
     191           6 :     PgStat_StatInjEntry *entry = pgstat_fetch_stat_injentry(name);
     192             : 
     193           6 :     if (entry == NULL)
     194           2 :         PG_RETURN_NULL();
     195             : 
     196           4 :     PG_RETURN_INT64(entry->numcalls);
     197             : }

Generated by: LCOV version 1.14