mirror of https://github.com/postgres/postgres
Likepull/173/head75534436a4
, this acts mainly as a template to show what can be achieved with fixed-numbered stats (like WAL, bgwriter, etc.) with the pluggable cumulative statistics APIs introduced in7949d95945
. Fixed-numbered stats are defined in their own file, named injection_stats_fixed.c, separated entirely from the variable-numbered case in injection_stats.c. This is mainly for clarity as having both examples in the same file would be confusing. Note that this commit uses the helper routines added in2eff9e678d
. The stats stored track globally the number of times injection points have been attached, detached or run. Two more fields should be added later for the number of times a point has been cached or loaded, but what's here is enough as a template. More TAP tests are added, providing coverage for fixed-numbered custom stats. Author: Michael Paquier Reviewed-by: Dmitry Dolgov, Bertrand Drouvot Discussion: https://postgr.es/m/Zmqm9j5EO0I4W8dx@paquier.xyz
parent
75534436a4
commit
f68cd847fa
@ -0,0 +1,192 @@ |
||||
/*--------------------------------------------------------------------------
|
||||
* |
||||
* injection_stats_fixed.c |
||||
* Code for fixed-numbered statistics of injection points. |
||||
* |
||||
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* IDENTIFICATION |
||||
* src/test/modules/injection_points/injection_stats_fixed.c |
||||
* |
||||
* ------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#include "postgres.h" |
||||
|
||||
#include "fmgr.h" |
||||
|
||||
#include "common/hashfn.h" |
||||
#include "funcapi.h" |
||||
#include "injection_stats.h" |
||||
#include "pgstat.h" |
||||
#include "utils/builtins.h" |
||||
#include "utils/pgstat_internal.h" |
||||
|
||||
/* Structures for statistics of injection points, fixed-size */ |
||||
typedef struct PgStat_StatInjFixedEntry |
||||
{ |
||||
PgStat_Counter numattach; /* number of points attached */ |
||||
PgStat_Counter numdetach; /* number of points detached */ |
||||
PgStat_Counter numrun; /* number of points run */ |
||||
TimestampTz stat_reset_timestamp; |
||||
} PgStat_StatInjFixedEntry; |
||||
|
||||
typedef struct PgStatShared_InjectionPointFixed |
||||
{ |
||||
LWLock lock; /* protects all the counters */ |
||||
uint32 changecount; |
||||
PgStat_StatInjFixedEntry stats; |
||||
PgStat_StatInjFixedEntry reset_offset; |
||||
} PgStatShared_InjectionPointFixed; |
||||
|
||||
/* Callbacks for fixed-numbered stats */ |
||||
static void injection_stats_fixed_init_shmem_cb(void *stats); |
||||
static void injection_stats_fixed_reset_all_cb(TimestampTz ts); |
||||
static void injection_stats_fixed_snapshot_cb(void); |
||||
|
||||
static const PgStat_KindInfo injection_stats_fixed = { |
||||
.name = "injection_points_fixed", |
||||
.fixed_amount = true, |
||||
|
||||
.shared_size = sizeof(PgStat_StatInjFixedEntry), |
||||
.shared_data_off = offsetof(PgStatShared_InjectionPointFixed, stats), |
||||
.shared_data_len = sizeof(((PgStatShared_InjectionPointFixed *) 0)->stats), |
||||
|
||||
.init_shmem_cb = injection_stats_fixed_init_shmem_cb, |
||||
.reset_all_cb = injection_stats_fixed_reset_all_cb, |
||||
.snapshot_cb = injection_stats_fixed_snapshot_cb, |
||||
}; |
||||
|
||||
/*
|
||||
* Kind ID reserved for statistics of injection points. |
||||
*/ |
||||
#define PGSTAT_KIND_INJECTION_FIXED 130 |
||||
|
||||
/* Track if fixed-numbered stats are loaded */ |
||||
static bool inj_fixed_loaded = false; |
||||
|
||||
static void |
||||
injection_stats_fixed_init_shmem_cb(void *stats) |
||||
{ |
||||
PgStatShared_InjectionPointFixed *stats_shmem = |
||||
(PgStatShared_InjectionPointFixed *) stats; |
||||
|
||||
LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA); |
||||
} |
||||
|
||||
static void |
||||
injection_stats_fixed_reset_all_cb(TimestampTz ts) |
||||
{ |
||||
PgStatShared_InjectionPointFixed *stats_shmem = |
||||
pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); |
||||
|
||||
LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE); |
||||
pgstat_copy_changecounted_stats(&stats_shmem->reset_offset, |
||||
&stats_shmem->stats, |
||||
sizeof(stats_shmem->stats), |
||||
&stats_shmem->changecount); |
||||
stats_shmem->stats.stat_reset_timestamp = ts; |
||||
LWLockRelease(&stats_shmem->lock); |
||||
} |
||||
|
||||
static void |
||||
injection_stats_fixed_snapshot_cb(void) |
||||
{ |
||||
PgStatShared_InjectionPointFixed *stats_shmem = |
||||
pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); |
||||
PgStat_StatInjFixedEntry *stat_snap = |
||||
pgstat_get_custom_snapshot_data(PGSTAT_KIND_INJECTION_FIXED); |
||||
PgStat_StatInjFixedEntry *reset_offset = &stats_shmem->reset_offset; |
||||
PgStat_StatInjFixedEntry reset; |
||||
|
||||
pgstat_copy_changecounted_stats(stat_snap, |
||||
&stats_shmem->stats, |
||||
sizeof(stats_shmem->stats), |
||||
&stats_shmem->changecount); |
||||
|
||||
LWLockAcquire(&stats_shmem->lock, LW_SHARED); |
||||
memcpy(&reset, reset_offset, sizeof(stats_shmem->stats)); |
||||
LWLockRelease(&stats_shmem->lock); |
||||
|
||||
/* compensate by reset offsets */ |
||||
#define FIXED_COMP(fld) stat_snap->fld -= reset.fld; |
||||
FIXED_COMP(numattach); |
||||
FIXED_COMP(numdetach); |
||||
FIXED_COMP(numrun); |
||||
#undef FIXED_COMP |
||||
} |
||||
|
||||
/*
|
||||
* Workhorse to do the registration work, called in _PG_init(). |
||||
*/ |
||||
void |
||||
pgstat_register_inj_fixed(void) |
||||
{ |
||||
pgstat_register_kind(PGSTAT_KIND_INJECTION_FIXED, &injection_stats_fixed); |
||||
|
||||
/* mark stats as loaded */ |
||||
inj_fixed_loaded = true; |
||||
} |
||||
|
||||
/*
|
||||
* Report fixed number of statistics for an injection point. |
||||
*/ |
||||
void |
||||
pgstat_report_inj_fixed(uint32 numattach, |
||||
uint32 numdetach, |
||||
uint32 numrun) |
||||
{ |
||||
PgStatShared_InjectionPointFixed *stats_shmem; |
||||
|
||||
/* leave if disabled */ |
||||
if (!inj_fixed_loaded) |
||||
return; |
||||
|
||||
stats_shmem = pgstat_get_custom_shmem_data(PGSTAT_KIND_INJECTION_FIXED); |
||||
|
||||
pgstat_begin_changecount_write(&stats_shmem->changecount); |
||||
stats_shmem->stats.numattach += numattach; |
||||
stats_shmem->stats.numdetach += numdetach; |
||||
stats_shmem->stats.numrun += numrun; |
||||
pgstat_end_changecount_write(&stats_shmem->changecount); |
||||
} |
||||
|
||||
/*
|
||||
* SQL function returning fixed-numbered statistics for injection points. |
||||
*/ |
||||
PG_FUNCTION_INFO_V1(injection_points_stats_fixed); |
||||
Datum |
||||
injection_points_stats_fixed(PG_FUNCTION_ARGS) |
||||
{ |
||||
TupleDesc tupdesc; |
||||
Datum values[3] = {0}; |
||||
bool nulls[3] = {0}; |
||||
PgStat_StatInjFixedEntry *stats; |
||||
|
||||
if (!inj_fixed_loaded) |
||||
PG_RETURN_NULL(); |
||||
|
||||
pgstat_snapshot_fixed(PGSTAT_KIND_INJECTION_FIXED); |
||||
stats = pgstat_get_custom_snapshot_data(PGSTAT_KIND_INJECTION_FIXED); |
||||
|
||||
/* Initialise attributes information in the tuple descriptor */ |
||||
tupdesc = CreateTemplateTupleDesc(3); |
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "numattach", |
||||
INT8OID, -1, 0); |
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "numdetach", |
||||
INT8OID, -1, 0); |
||||
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "numrun", |
||||
INT8OID, -1, 0); |
||||
BlessTupleDesc(tupdesc); |
||||
|
||||
values[0] = Int64GetDatum(stats->numattach); |
||||
values[1] = Int64GetDatum(stats->numdetach); |
||||
values[2] = Int64GetDatum(stats->numrun); |
||||
nulls[0] = false; |
||||
nulls[1] = false; |
||||
nulls[2] = false; |
||||
|
||||
/* Returns the record as Datum */ |
||||
PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls))); |
||||
} |
Loading…
Reference in new issue