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
1249 andres@anarazel.de 46 :CBC 24871 : pgstat_report_wal(bool force)
47 : : {
48 : : bool nowait;
49 : :
50 : : /* like in pgstat.c, don't wait for lock acquisition when !force */
711 michael@paquier.xyz 51 : 24871 : nowait = !force;
52 : :
53 : : /* flush wal stats */
192 54 : 24871 : (void) pgstat_wal_flush_cb(nowait);
179 55 : 24871 : pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_WAL);
56 : :
57 : : /* flush IO stats */
711 58 : 24871 : pgstat_flush_io(nowait);
187 59 : 24871 : (void) pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_IO);
1249 andres@anarazel.de 60 : 24871 : }
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
40 michael@paquier.xyz 78 : 55869 : pgstat_wal_have_pending(void)
79 : : {
80 : 55869 : 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
362 91 : 55869 : pgstat_wal_flush_cb(bool nowait)
92 : : {
1249 andres@anarazel.de 93 : 55869 : PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
891 94 : 55869 : WalUsage wal_usage_diff = {0};
95 : :
1249 96 [ + + - + ]: 55869 : Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
97 [ + - - + ]: 55869 : 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 : : */
40 michael@paquier.xyz 104 [ + + ]: 55869 : if (!pgstat_wal_have_pending())
1249 andres@anarazel.de 105 : 45362 : 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 : : */
891 112 : 10507 : WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevWalUsage);
113 : :
1249 114 [ + + ]: 10507 : if (!nowait)
115 : 8411 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
116 [ - + ]: 2096 : else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
1249 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)
891 andres@anarazel.de 121 :CBC 10507 : WALSTAT_ACC(wal_records, wal_usage_diff);
122 : 10507 : WALSTAT_ACC(wal_fpi, wal_usage_diff);
123 : 10507 : WALSTAT_ACC(wal_bytes, wal_usage_diff);
201 michael@paquier.xyz 124 : 10507 : WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
125 : : #undef WALSTAT_ACC
126 : :
1249 andres@anarazel.de 127 : 10507 : LWLockRelease(&stats_shmem->lock);
128 : :
129 : : /*
130 : : * Save the current counters for the subsequent calculation of WAL usage.
131 : : */
132 : 10507 : prevWalUsage = pgWalUsage;
133 : :
134 : 10507 : return false;
135 : : }
136 : :
137 : : void
366 michael@paquier.xyz 138 : 18773 : pgstat_wal_init_backend_cb(void)
139 : : {
140 : : /*
141 : : * Initialize prevWalUsage with pgWalUsage so that pgstat_wal_flush_cb()
142 : : * can calculate how much pgWalUsage counters are increased by subtracting
143 : : * prevWalUsage from pgWalUsage.
144 : : */
1265 andres@anarazel.de 145 : 18773 : prevWalUsage = pgWalUsage;
146 : 18773 : }
147 : :
148 : : void
422 michael@paquier.xyz 149 : 1029 : pgstat_wal_init_shmem_cb(void *stats)
150 : : {
151 : 1029 : PgStatShared_Wal *stats_shmem = (PgStatShared_Wal *) stats;
152 : :
153 : 1029 : LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA);
154 : 1029 : }
155 : :
156 : : void
1249 andres@anarazel.de 157 : 226 : pgstat_wal_reset_all_cb(TimestampTz ts)
158 : : {
159 : 226 : PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
160 : :
161 : 226 : LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
162 : 226 : memset(&stats_shmem->stats, 0, sizeof(stats_shmem->stats));
163 : 226 : stats_shmem->stats.stat_reset_timestamp = ts;
164 : 226 : LWLockRelease(&stats_shmem->lock);
165 : 226 : }
166 : :
167 : : void
168 : 666 : pgstat_wal_snapshot_cb(void)
169 : : {
170 : 666 : PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
171 : :
172 : 666 : LWLockAcquire(&stats_shmem->lock, LW_SHARED);
173 : 666 : memcpy(&pgStatLocal.snapshot.wal, &stats_shmem->stats,
174 : : sizeof(pgStatLocal.snapshot.wal));
175 : 666 : LWLockRelease(&stats_shmem->lock);
1265 176 : 666 : }
|