Age Owner Branch data TLA Line data Source code
1 : : /* -------------------------------------------------------------------------
2 : : *
3 : : * pgstat_wal.c
4 : : * Implementation of WAL statistics.
5 : : *
6 : : * This file contains the implementation of WAL statistics. It is kept
7 : : * separate from pgstat.c to enforce the line between the statistics access /
8 : : * storage implementation and the details about individual types of
9 : : * statistics.
10 : : *
11 : : * Copyright (c) 2001-2025, PostgreSQL Global Development Group
12 : : *
13 : : * IDENTIFICATION
14 : : * src/backend/utils/activity/pgstat_wal.c
15 : : * -------------------------------------------------------------------------
16 : : */
17 : :
18 : : #include "postgres.h"
19 : :
20 : : #include "executor/instrument.h"
21 : : #include "utils/pgstat_internal.h"
22 : :
23 : :
24 : : /*
25 : : * WAL usage counters saved from pgWalUsage at the previous call to
26 : : * pgstat_report_wal(). This is used to calculate how much WAL usage
27 : : * happens between pgstat_report_wal() calls, by subtracting
28 : : * the previous counters from the current ones.
29 : : */
30 : : static WalUsage prevWalUsage;
31 : :
32 : :
33 : : /*
34 : : * Calculate how much WAL usage counters have increased and update
35 : : * shared WAL and IO statistics.
36 : : *
37 : : * Must be called by processes that generate WAL, that do not call
38 : : * pgstat_report_stat(), like walwriter.
39 : : *
40 : : * "force" set to true ensures that the statistics are flushed; note that
41 : : * this needs to acquire the pgstat shmem LWLock, waiting on it. When
42 : : * set to false, the statistics may not be flushed if the lock could not
43 : : * be acquired.
44 : : */
45 : : void
1351 andres@anarazel.de 46 :CBC 26377 : pgstat_report_wal(bool force)
47 : : {
48 : : bool nowait;
49 : :
50 : : /* like in pgstat.c, don't wait for lock acquisition when !force */
813 michael@paquier.xyz 51 : 26377 : nowait = !force;
52 : :
53 : : /* flush wal stats */
294 54 : 26377 : (void) pgstat_wal_flush_cb(nowait);
281 55 : 26377 : pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_WAL);
56 : :
57 : : /* flush IO stats */
813 58 : 26377 : pgstat_flush_io(nowait);
289 59 : 26377 : (void) pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_IO);
1351 andres@anarazel.de 60 : 26377 : }
61 : :
62 : : /*
63 : : * Support function for the SQL-callable pgstat* functions. Returns
64 : : * a pointer to the WAL statistics struct.
65 : : */
66 : : PgStat_WalStats *
67 : 35 : pgstat_fetch_stat_wal(void)
68 : : {
69 : 35 : pgstat_snapshot_fixed(PGSTAT_KIND_WAL);
70 : :
71 : 35 : return &pgStatLocal.snapshot.wal;
72 : : }
73 : :
74 : : /*
75 : : * To determine whether WAL usage happened.
76 : : */
77 : : static inline bool
142 michael@paquier.xyz 78 : 59204 : pgstat_wal_have_pending(void)
79 : : {
80 : 59204 : return pgWalUsage.wal_records != prevWalUsage.wal_records;
81 : : }
82 : :
83 : : /*
84 : : * Calculate how much WAL usage counters have increased by subtracting the
85 : : * previous counters from the current ones.
86 : : *
87 : : * If nowait is true, this function returns true if the lock could not be
88 : : * acquired. Otherwise return false.
89 : : */
90 : : bool
464 91 : 59204 : pgstat_wal_flush_cb(bool nowait)
92 : : {
1351 andres@anarazel.de 93 : 59204 : PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
993 94 : 59204 : WalUsage wal_usage_diff = {0};
95 : :
1351 96 [ + + - + ]: 59204 : Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
97 [ + - - + ]: 59204 : Assert(pgStatLocal.shmem != NULL &&
98 : : !pgStatLocal.shmem->is_shutdown);
99 : :
100 : : /*
101 : : * This function can be called even if nothing at all has happened. Avoid
102 : : * taking lock for nothing in that case.
103 : : */
142 michael@paquier.xyz 104 [ + + ]: 59204 : if (!pgstat_wal_have_pending())
1351 andres@anarazel.de 105 : 47902 : return false;
106 : :
107 : : /*
108 : : * We don't update the WAL usage portion of the local WalStats elsewhere.
109 : : * Calculate how much WAL usage counters were increased by subtracting the
110 : : * previous counters from the current ones.
111 : : */
993 112 : 11302 : WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevWalUsage);
113 : :
1351 114 [ + + ]: 11302 : if (!nowait)
115 : 8737 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
116 [ - + ]: 2565 : else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
1351 andres@anarazel.de 117 :UBC 0 : return true;
118 : :
119 : : #define WALSTAT_ACC(fld, var_to_add) \
120 : : (stats_shmem->stats.wal_counters.fld += var_to_add.fld)
993 andres@anarazel.de 121 :CBC 11302 : WALSTAT_ACC(wal_records, wal_usage_diff);
122 : 11302 : WALSTAT_ACC(wal_fpi, wal_usage_diff);
123 : 11302 : WALSTAT_ACC(wal_bytes, wal_usage_diff);
50 michael@paquier.xyz 124 :GNC 11302 : WALSTAT_ACC(wal_fpi_bytes, wal_usage_diff);
303 michael@paquier.xyz 125 :CBC 11302 : WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
126 : : #undef WALSTAT_ACC
127 : :
1351 andres@anarazel.de 128 : 11302 : LWLockRelease(&stats_shmem->lock);
129 : :
130 : : /*
131 : : * Save the current counters for the subsequent calculation of WAL usage.
132 : : */
133 : 11302 : prevWalUsage = pgWalUsage;
134 : :
135 : 11302 : return false;
136 : : }
137 : :
138 : : void
468 michael@paquier.xyz 139 : 19587 : pgstat_wal_init_backend_cb(void)
140 : : {
141 : : /*
142 : : * Initialize prevWalUsage with pgWalUsage so that pgstat_wal_flush_cb()
143 : : * can calculate how much pgWalUsage counters are increased by subtracting
144 : : * prevWalUsage from pgWalUsage.
145 : : */
1367 andres@anarazel.de 146 : 19587 : prevWalUsage = pgWalUsage;
147 : 19587 : }
148 : :
149 : : void
524 michael@paquier.xyz 150 : 1069 : pgstat_wal_init_shmem_cb(void *stats)
151 : : {
152 : 1069 : PgStatShared_Wal *stats_shmem = (PgStatShared_Wal *) stats;
153 : :
154 : 1069 : LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA);
155 : 1069 : }
156 : :
157 : : void
1351 andres@anarazel.de 158 : 230 : pgstat_wal_reset_all_cb(TimestampTz ts)
159 : : {
160 : 230 : PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
161 : :
162 : 230 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
163 : 230 : memset(&stats_shmem->stats, 0, sizeof(stats_shmem->stats));
164 : 230 : stats_shmem->stats.stat_reset_timestamp = ts;
165 : 230 : LWLockRelease(&stats_shmem->lock);
166 : 230 : }
167 : :
168 : : void
169 : 698 : pgstat_wal_snapshot_cb(void)
170 : : {
171 : 698 : PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
172 : :
173 : 698 : LWLockAcquire(&stats_shmem->lock, LW_SHARED);
174 : 698 : memcpy(&pgStatLocal.snapshot.wal, &stats_shmem->stats,
175 : : sizeof(pgStatLocal.snapshot.wal));
176 : 698 : LWLockRelease(&stats_shmem->lock);
1367 177 : 698 : }
|