1 /*--------------------------------------------------------------------------
4 * Code for statistics of injection points.
6 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/test/modules/injection_points/injection_stats.c
12 * -------------------------------------------------------------------------
19 #include "common/hashfn.h"
20 #include "injection_stats.h"
22 #include "utils/builtins.h"
23 #include "utils/pgstat_internal.h"
25 /* Structures for statistics of injection points */
26 typedef struct PgStat_StatInjEntry
28 PgStat_Counter numcalls
; /* number of times point has been run */
29 } PgStat_StatInjEntry
;
31 typedef struct PgStatShared_InjectionPoint
33 PgStatShared_Common header
;
34 PgStat_StatInjEntry stats
;
35 } PgStatShared_InjectionPoint
;
37 static bool injection_stats_flush_cb(PgStat_EntryRef
*entry_ref
, bool nowait
);
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,
44 /* Injection points are system-wide */
45 .accessed_across_databases
= true,
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
,
55 * Compute stats entry idx from point name with an 8-byte hash.
57 #define PGSTAT_INJ_IDX(name) hash_bytes_extended((const unsigned char *) name, strlen(name), 0)
60 * Kind ID reserved for statistics of injection points.
62 #define PGSTAT_KIND_INJECTION 129
64 /* Track if stats are loaded */
65 static bool inj_stats_loaded
= false;
68 * Callback for stats handling
71 injection_stats_flush_cb(PgStat_EntryRef
*entry_ref
, bool nowait
)
73 PgStat_StatInjEntry
*localent
;
74 PgStatShared_InjectionPoint
*shfuncent
;
76 localent
= (PgStat_StatInjEntry
*) entry_ref
->pending
;
77 shfuncent
= (PgStatShared_InjectionPoint
*) entry_ref
->shared_stats
;
79 if (!pgstat_lock_entry(entry_ref
, nowait
))
82 shfuncent
->stats
.numcalls
+= localent
->numcalls
;
87 * Support function for the SQL-callable pgstat* functions. Returns
88 * a pointer to the injection point statistics struct.
90 static PgStat_StatInjEntry
*
91 pgstat_fetch_stat_injentry(const char *name
)
93 PgStat_StatInjEntry
*entry
= NULL
;
95 if (!inj_stats_loaded
|| !inj_stats_enabled
)
98 /* Compile the lookup key as a hash of the point name */
99 entry
= (PgStat_StatInjEntry
*) pgstat_fetch_entry(PGSTAT_KIND_INJECTION
,
101 PGSTAT_INJ_IDX(name
));
106 * Workhorse to do the registration work, called in _PG_init().
109 pgstat_register_inj(void)
111 pgstat_register_kind(PGSTAT_KIND_INJECTION
, &injection_stats
);
113 /* mark stats as loaded */
114 inj_stats_loaded
= true;
118 * Report injection point creation.
121 pgstat_create_inj(const char *name
)
123 PgStat_EntryRef
*entry_ref
;
124 PgStatShared_InjectionPoint
*shstatent
;
126 /* leave if disabled */
127 if (!inj_stats_loaded
|| !inj_stats_enabled
)
130 entry_ref
= pgstat_get_entry_ref_locked(PGSTAT_KIND_INJECTION
, InvalidOid
,
131 PGSTAT_INJ_IDX(name
), false);
132 shstatent
= (PgStatShared_InjectionPoint
*) entry_ref
->shared_stats
;
134 /* initialize shared memory data */
135 memset(&shstatent
->stats
, 0, sizeof(shstatent
->stats
));
136 pgstat_unlock_entry(entry_ref
);
140 * Report injection point drop.
143 pgstat_drop_inj(const char *name
)
145 /* leave if disabled */
146 if (!inj_stats_loaded
|| !inj_stats_enabled
)
149 if (!pgstat_drop_entry(PGSTAT_KIND_INJECTION
, InvalidOid
,
150 PGSTAT_INJ_IDX(name
)))
151 pgstat_request_entry_refs_gc();
155 * Report statistics for injection point.
157 * This is simple because the set of stats to report currently is simple:
158 * track the number of times a point has been run.
161 pgstat_report_inj(const char *name
)
163 PgStat_EntryRef
*entry_ref
;
164 PgStatShared_InjectionPoint
*shstatent
;
165 PgStat_StatInjEntry
*statent
;
167 /* leave if disabled */
168 if (!inj_stats_loaded
|| !inj_stats_enabled
)
171 entry_ref
= pgstat_get_entry_ref_locked(PGSTAT_KIND_INJECTION
, InvalidOid
,
172 PGSTAT_INJ_IDX(name
), false);
174 shstatent
= (PgStatShared_InjectionPoint
*) entry_ref
->shared_stats
;
175 statent
= &shstatent
->stats
;
177 /* Update the injection point statistics */
180 pgstat_unlock_entry(entry_ref
);
184 * SQL function returning the number of times an injection point
187 PG_FUNCTION_INFO_V1(injection_points_stats_numcalls
);
189 injection_points_stats_numcalls(PG_FUNCTION_ARGS
)
191 char *name
= text_to_cstring(PG_GETARG_TEXT_PP(0));
192 PgStat_StatInjEntry
*entry
= pgstat_fetch_stat_injentry(name
);
197 PG_RETURN_INT64(entry
->numcalls
);