LCOV - code coverage report
Current view: top level - src/backend/utils/activity - pgstat_wal.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 98.0 % 50 49
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            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-2026, 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
      46        32609 : pgstat_report_wal(bool force)
      47              : {
      48              :     bool        nowait;
      49              : 
      50              :     /* like in pgstat.c, don't wait for lock acquisition when !force */
      51        32609 :     nowait = !force;
      52              : 
      53              :     /* flush wal stats */
      54        32609 :     (void) pgstat_wal_flush_cb(nowait);
      55        32609 :     pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_WAL);
      56              : 
      57              :     /* flush IO stats */
      58        32609 :     pgstat_flush_io(nowait);
      59        32609 :     (void) pgstat_flush_backend(nowait, PGSTAT_BACKEND_FLUSH_IO);
      60        32609 : }
      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
      78        69323 : pgstat_wal_have_pending(void)
      79              : {
      80        69323 :     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
      91        69323 : pgstat_wal_flush_cb(bool nowait)
      92              : {
      93        69323 :     PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
      94        69323 :     WalUsage    wal_usage_diff = {0};
      95              : 
      96              :     Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
      97              :     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              :      */
     104        69323 :     if (!pgstat_wal_have_pending())
     105        57511 :         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              :      */
     112        11812 :     WalUsageAccumDiff(&wal_usage_diff, &pgWalUsage, &prevWalUsage);
     113              : 
     114        11812 :     if (!nowait)
     115         9641 :         LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
     116         2171 :     else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
     117            0 :         return true;
     118              : 
     119              : #define WALSTAT_ACC(fld, var_to_add) \
     120              :     (stats_shmem->stats.wal_counters.fld += var_to_add.fld)
     121        11812 :     WALSTAT_ACC(wal_records, wal_usage_diff);
     122        11812 :     WALSTAT_ACC(wal_fpi, wal_usage_diff);
     123        11812 :     WALSTAT_ACC(wal_bytes, wal_usage_diff);
     124        11812 :     WALSTAT_ACC(wal_fpi_bytes, wal_usage_diff);
     125        11812 :     WALSTAT_ACC(wal_buffers_full, wal_usage_diff);
     126              : #undef WALSTAT_ACC
     127              : 
     128        11812 :     LWLockRelease(&stats_shmem->lock);
     129              : 
     130              :     /*
     131              :      * Save the current counters for the subsequent calculation of WAL usage.
     132              :      */
     133        11812 :     prevWalUsage = pgWalUsage;
     134              : 
     135        11812 :     return false;
     136              : }
     137              : 
     138              : void
     139        23004 : 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              :      */
     146        23004 :     prevWalUsage = pgWalUsage;
     147        23004 : }
     148              : 
     149              : void
     150         1140 : pgstat_wal_init_shmem_cb(void *stats)
     151              : {
     152         1140 :     PgStatShared_Wal *stats_shmem = (PgStatShared_Wal *) stats;
     153              : 
     154         1140 :     LWLockInitialize(&stats_shmem->lock, LWTRANCHE_PGSTATS_DATA);
     155         1140 : }
     156              : 
     157              : void
     158          243 : pgstat_wal_reset_all_cb(TimestampTz ts)
     159              : {
     160          243 :     PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
     161              : 
     162          243 :     LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
     163          243 :     memset(&stats_shmem->stats, 0, sizeof(stats_shmem->stats));
     164          243 :     stats_shmem->stats.stat_reset_timestamp = ts;
     165          243 :     LWLockRelease(&stats_shmem->lock);
     166          243 : }
     167              : 
     168              : void
     169          745 : pgstat_wal_snapshot_cb(void)
     170              : {
     171          745 :     PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
     172              : 
     173          745 :     LWLockAcquire(&stats_shmem->lock, LW_SHARED);
     174          745 :     memcpy(&pgStatLocal.snapshot.wal, &stats_shmem->stats,
     175              :            sizeof(pgStatLocal.snapshot.wal));
     176          745 :     LWLockRelease(&stats_shmem->lock);
     177          745 : }
        

Generated by: LCOV version 2.0-1