Age Owner Branch data TLA Line data Source code
1 : : /*--------------------------------------------------------------------------
2 : : *
3 : : * test_custom_fixed_stats.c
4 : : * Test module for fixed-sized custom pgstats
5 : : *
6 : : * Copyright (c) 2025-2026, PostgreSQL Global Development Group
7 : : *
8 : : * IDENTIFICATION
9 : : * src/test/modules/test_custom_stats/test_custom_fixed_stats.c
10 : : *
11 : : * -------------------------------------------------------------------------
12 : : */
13 : :
14 : : #include "postgres.h"
15 : :
16 : : #include "access/htup_details.h"
17 : : #include "funcapi.h"
18 : : #include "pgstat.h"
19 : : #include "utils/builtins.h"
20 : : #include "utils/pgstat_internal.h"
21 : : #include "utils/timestamp.h"
22 : :
97 michael@paquier.xyz 23 :GNC 3 : PG_MODULE_MAGIC_EXT(
24 : : .name = "test_custom_fixed_stats",
25 : : .version = PG_VERSION
26 : : );
27 : :
28 : : /* Fixed-amount custom statistics entry */
29 : : typedef struct PgStat_StatCustomFixedEntry
30 : : {
31 : : PgStat_Counter numcalls; /* # of times update function called */
32 : : TimestampTz stat_reset_timestamp;
33 : : } PgStat_StatCustomFixedEntry;
34 : :
35 : : typedef struct PgStatShared_CustomFixedEntry
36 : : {
37 : : LWLock lock; /* protects counters */
38 : : uint32 changecount; /* for atomic reads */
39 : : PgStat_StatCustomFixedEntry stats; /* current counters */
40 : : PgStat_StatCustomFixedEntry reset_offset; /* reset baseline */
41 : : } PgStatShared_CustomFixedEntry;
42 : :
43 : : /* Callbacks for fixed-amount statistics */
44 : : static void test_custom_stats_fixed_init_shmem_cb(void *stats);
45 : : static void test_custom_stats_fixed_reset_all_cb(TimestampTz ts);
46 : : static void test_custom_stats_fixed_snapshot_cb(void);
47 : :
48 : : static const PgStat_KindInfo custom_stats = {
49 : : .name = "test_custom_fixed_stats",
50 : : .fixed_amount = true, /* exactly one entry */
51 : : .write_to_file = true, /* persist to stats file */
52 : :
53 : : .shared_size = sizeof(PgStat_StatCustomFixedEntry),
54 : : .shared_data_off = offsetof(PgStatShared_CustomFixedEntry, stats),
55 : : .shared_data_len = sizeof(((PgStatShared_CustomFixedEntry *) 0)->stats),
56 : :
57 : : .init_shmem_cb = test_custom_stats_fixed_init_shmem_cb,
58 : : .reset_all_cb = test_custom_stats_fixed_reset_all_cb,
59 : : .snapshot_cb = test_custom_stats_fixed_snapshot_cb,
60 : : };
61 : :
62 : : /*
63 : : * Kind ID for test_custom_fixed_stats.
64 : : */
65 : : #define PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS 26
66 : :
67 : : /*--------------------------------------------------------------------------
68 : : * Module initialization
69 : : *--------------------------------------------------------------------------
70 : : */
71 : :
72 : : void
73 : 3 : _PG_init(void)
74 : : {
75 : : /* Must be loaded via shared_preload_libraries */
76 [ - + ]: 3 : if (!process_shared_preload_libraries_in_progress)
97 michael@paquier.xyz 77 :UNC 0 : return;
78 : :
79 : : /* Register custom statistics kind */
97 michael@paquier.xyz 80 :GNC 3 : pgstat_register_kind(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS, &custom_stats);
81 : : }
82 : :
83 : : /*
84 : : * test_custom_stats_fixed_init_shmem_cb
85 : : * Initialize shared memory structure
86 : : */
87 : : static void
88 : 3 : test_custom_stats_fixed_init_shmem_cb(void *stats)
89 : : {
90 : 3 : PgStatShared_CustomFixedEntry *stats_shmem =
91 : : (PgStatShared_CustomFixedEntry *) stats;
92 : :
93 : 3 : LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA);
94 : 3 : }
95 : :
96 : : /*
97 : : * test_custom_stats_fixed_reset_all_cb
98 : : * Reset the fixed-sized stats
99 : : */
100 : : static void
101 : 1 : test_custom_stats_fixed_reset_all_cb(TimestampTz ts)
102 : : {
103 : : PgStatShared_CustomFixedEntry *stats_shmem =
104 : 1 : pgstat_get_custom_shmem_data(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
105 : :
106 : : /* see explanation above PgStatShared_Archiver for the reset protocol */
107 : 1 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
108 : 1 : pgstat_copy_changecounted_stats(&stats_shmem->reset_offset,
109 : 1 : &stats_shmem->stats,
110 : : sizeof(stats_shmem->stats),
111 : : &stats_shmem->changecount);
112 : 1 : stats_shmem->stats.stat_reset_timestamp = ts;
113 : 1 : LWLockRelease(&stats_shmem->lock);
114 : 1 : }
115 : :
116 : : /*
117 : : * test_custom_stats_fixed_snapshot_cb
118 : : * Copy current stats to snapshot area
119 : : */
120 : : static void
121 : 3 : test_custom_stats_fixed_snapshot_cb(void)
122 : : {
123 : : PgStatShared_CustomFixedEntry *stats_shmem =
124 : 3 : pgstat_get_custom_shmem_data(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
125 : : PgStat_StatCustomFixedEntry *stat_snap =
126 : 3 : pgstat_get_custom_snapshot_data(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
127 : 3 : PgStat_StatCustomFixedEntry *reset_offset = &stats_shmem->reset_offset;
128 : : PgStat_StatCustomFixedEntry reset;
129 : :
130 : 3 : pgstat_copy_changecounted_stats(stat_snap,
131 : 3 : &stats_shmem->stats,
132 : : sizeof(stats_shmem->stats),
133 : : &stats_shmem->changecount);
134 : :
135 : 3 : LWLockAcquire(&stats_shmem->lock, LW_SHARED);
136 : 3 : memcpy(&reset, reset_offset, sizeof(stats_shmem->stats));
137 : 3 : LWLockRelease(&stats_shmem->lock);
138 : :
139 : : /* Apply reset offsets */
140 : : #define FIXED_COMP(fld) stat_snap->fld -= reset.fld;
141 : 3 : FIXED_COMP(numcalls);
142 : : #undef FIXED_COMP
143 : 3 : }
144 : :
145 : : /*--------------------------------------------------------------------------
146 : : * SQL-callable functions
147 : : *--------------------------------------------------------------------------
148 : : */
149 : :
150 : : /*
151 : : * test_custom_stats_fixed_update
152 : : * Increment call counter
153 : : */
154 : 7 : PG_FUNCTION_INFO_V1(test_custom_stats_fixed_update);
155 : : Datum
156 : 6 : test_custom_stats_fixed_update(PG_FUNCTION_ARGS)
157 : : {
158 : : PgStatShared_CustomFixedEntry *stats_shmem;
159 : :
160 : 6 : stats_shmem = pgstat_get_custom_shmem_data(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
161 : :
162 : 6 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
163 : :
164 : 6 : pgstat_begin_changecount_write(&stats_shmem->changecount);
165 : 6 : stats_shmem->stats.numcalls++;
166 : 6 : pgstat_end_changecount_write(&stats_shmem->changecount);
167 : :
168 : 6 : LWLockRelease(&stats_shmem->lock);
169 : :
170 : 6 : PG_RETURN_VOID();
171 : : }
172 : :
173 : : /*
174 : : * test_custom_stats_fixed_reset
175 : : * Reset statistics by calling pgstat system
176 : : */
177 : 1 : PG_FUNCTION_INFO_V1(test_custom_stats_fixed_reset);
178 : : Datum
97 michael@paquier.xyz 179 :UNC 0 : test_custom_stats_fixed_reset(PG_FUNCTION_ARGS)
180 : : {
181 : 0 : pgstat_reset_of_kind(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
182 : :
183 : 0 : PG_RETURN_VOID();
184 : : }
185 : :
186 : : /*
187 : : * test_custom_stats_fixed_report
188 : : * Return current counter values
189 : : */
97 michael@paquier.xyz 190 :GNC 3 : PG_FUNCTION_INFO_V1(test_custom_stats_fixed_report);
191 : : Datum
192 : 2 : test_custom_stats_fixed_report(PG_FUNCTION_ARGS)
193 : : {
194 : : TupleDesc tupdesc;
195 : 2 : Datum values[2] = {0};
196 : 2 : bool nulls[2] = {false};
197 : : PgStat_StatCustomFixedEntry *stats;
198 : :
199 : : /* Take snapshot (applies reset offsets) */
200 : 2 : pgstat_snapshot_fixed(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
201 : 2 : stats = pgstat_get_custom_snapshot_data(PGSTAT_KIND_TEST_CUSTOM_FIXED_STATS);
202 : :
203 : : /* Build return tuple */
204 : 2 : tupdesc = CreateTemplateTupleDesc(2);
205 : 2 : TupleDescInitEntry(tupdesc, (AttrNumber) 1, "numcalls",
206 : : INT8OID, -1, 0);
207 : 2 : TupleDescInitEntry(tupdesc, (AttrNumber) 2, "stats_reset",
208 : : TIMESTAMPTZOID, -1, 0);
209 : 2 : BlessTupleDesc(tupdesc);
210 : :
211 : 2 : values[0] = Int64GetDatum(stats->numcalls);
212 : :
213 : : /* Handle uninitialized timestamp (no reset yet) */
214 [ + + ]: 2 : if (stats->stat_reset_timestamp == 0)
215 : : {
216 : 1 : nulls[1] = true;
217 : : }
218 : : else
219 : : {
220 : 1 : values[1] = TimestampTzGetDatum(stats->stat_reset_timestamp);
221 : : }
222 : :
223 : : /* Return as tuple */
224 : 2 : PG_RETURN_DATUM(HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)));
225 : : }
|