summaryrefslogtreecommitdiff
path: root/src/backend/utils/activity/pgstat_wal.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/activity/pgstat_wal.c')
-rw-r--r--src/backend/utils/activity/pgstat_wal.c175
1 files changed, 95 insertions, 80 deletions
diff --git a/src/backend/utils/activity/pgstat_wal.c b/src/backend/utils/activity/pgstat_wal.c
index 8855598f52..5a878bd115 100644
--- a/src/backend/utils/activity/pgstat_wal.c
+++ b/src/backend/utils/activity/pgstat_wal.c
@@ -21,13 +21,7 @@
#include "executor/instrument.h"
-/*
- * WAL global statistics counters. Stored directly in a stats message
- * structure so they can be sent without needing to copy things around. We
- * assume these init to zeroes.
- */
-PgStat_MsgWal WalStats;
-
+PgStat_WalStats PendingWalStats = {0};
/*
* WAL usage counters saved from pgWALUsage at the previous call to
@@ -39,101 +33,100 @@ static WalUsage prevWalUsage;
/*
- * Send WAL statistics to the collector.
+ * Calculate how much WAL usage counters have increased and update
+ * shared statistics.
*
- * If 'force' is not set, WAL stats message is only sent if enough time has
- * passed since last one was sent to reach PGSTAT_STAT_INTERVAL.
+ * Must be called by processes that generate WAL, that do not call
+ * pgstat_report_stat(), like walwriter.
*/
void
pgstat_report_wal(bool force)
{
- static TimestampTz sendTime = 0;
+ pgstat_flush_wal(force);
+}
+
+/*
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * a pointer to the WAL statistics struct.
+ */
+PgStat_WalStats *
+pgstat_fetch_stat_wal(void)
+{
+ pgstat_snapshot_fixed(PGSTAT_KIND_WAL);
+
+ return &pgStatLocal.snapshot.wal;
+}
+
+/*
+ * Calculate how much WAL usage counters have increased by subtracting the
+ * previous counters from the current ones.
+ *
+ * If nowait is true, this function returns true if the lock could not be
+ * acquired. Otherwise return false.
+ */
+bool
+pgstat_flush_wal(bool nowait)
+{
+ PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
+ WalUsage diff = {0};
+
+ Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
+ Assert(pgStatLocal.shmem != NULL &&
+ !pgStatLocal.shmem->is_shutdown);
/*
- * This function can be called even if nothing at all has happened. In
- * this case, avoid sending a completely empty message to the stats
- * collector.
- *
- * Check wal_records counter to determine whether any WAL activity has
- * happened since last time. Note that other WalUsage counters don't need
- * to be checked because they are incremented always together with
- * wal_records counter.
- *
- * m_wal_buffers_full also doesn't need to be checked because it's
- * incremented only when at least one WAL record is generated (i.e.,
- * wal_records counter is incremented). But for safely, we assert that
- * m_wal_buffers_full is always zero when no WAL record is generated
- *
- * This function can be called by a process like walwriter that normally
- * generates no WAL records. To determine whether any WAL activity has
- * happened at that process since the last time, the numbers of WAL writes
- * and syncs are also checked.
+ * This function can be called even if nothing at all has happened. Avoid
+ * taking lock for nothing in that case.
*/
- if (pgWalUsage.wal_records == prevWalUsage.wal_records &&
- WalStats.m_wal_write == 0 && WalStats.m_wal_sync == 0)
- {
- Assert(WalStats.m_wal_buffers_full == 0);
- return;
- }
-
- if (!force)
- {
- TimestampTz now = GetCurrentTimestamp();
-
- /*
- * Don't send a message unless it's been at least PGSTAT_STAT_INTERVAL
- * msec since we last sent one to avoid overloading the stats
- * collector.
- */
- if (!TimestampDifferenceExceeds(sendTime, now, PGSTAT_STAT_INTERVAL))
- return;
- sendTime = now;
- }
+ if (!pgstat_have_pending_wal())
+ return false;
/*
- * Set the counters related to generated WAL data if the counters were
- * updated.
+ * We don't update the WAL usage portion of the local WalStats elsewhere.
+ * Calculate how much WAL usage counters were increased by subtracting the
+ * previous counters from the current ones.
*/
- if (pgWalUsage.wal_records != prevWalUsage.wal_records)
- {
- WalUsage walusage;
-
- /*
- * Calculate how much WAL usage counters were increased by subtracting
- * the previous counters from the current ones. Fill the results in
- * WAL stats message.
- */
- MemSet(&walusage, 0, sizeof(WalUsage));
- WalUsageAccumDiff(&walusage, &pgWalUsage, &prevWalUsage);
-
- WalStats.m_wal_records = walusage.wal_records;
- WalStats.m_wal_fpi = walusage.wal_fpi;
- WalStats.m_wal_bytes = walusage.wal_bytes;
-
- /*
- * Save the current counters for the subsequent calculation of WAL
- * usage.
- */
- prevWalUsage = pgWalUsage;
- }
+ WalUsageAccumDiff(&diff, &pgWalUsage, &prevWalUsage);
+ PendingWalStats.wal_records = diff.wal_records;
+ PendingWalStats.wal_fpi = diff.wal_fpi;
+ PendingWalStats.wal_bytes = diff.wal_bytes;
+
+ if (!nowait)
+ LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
+ else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
+ return true;
+
+#define WALSTAT_ACC(fld) stats_shmem->stats.fld += PendingWalStats.fld
+ WALSTAT_ACC(wal_records);
+ WALSTAT_ACC(wal_fpi);
+ WALSTAT_ACC(wal_bytes);
+ WALSTAT_ACC(wal_buffers_full);
+ WALSTAT_ACC(wal_write);
+ WALSTAT_ACC(wal_sync);
+ WALSTAT_ACC(wal_write_time);
+ WALSTAT_ACC(wal_sync_time);
+#undef WALSTAT_ACC
+
+ LWLockRelease(&stats_shmem->lock);
/*
- * Prepare and send the message
+ * Save the current counters for the subsequent calculation of WAL usage.
*/
- pgstat_setheader(&WalStats.m_hdr, PGSTAT_MTYPE_WAL);
- pgstat_send(&WalStats, sizeof(WalStats));
+ prevWalUsage = pgWalUsage;
/*
* Clear out the statistics buffer, so it can be re-used.
*/
- MemSet(&WalStats, 0, sizeof(WalStats));
+ MemSet(&PendingWalStats, 0, sizeof(PendingWalStats));
+
+ return false;
}
void
pgstat_init_wal(void)
{
/*
- * Initialize prevWalUsage with pgWalUsage so that pgstat_report_wal() can
+ * Initialize prevWalUsage with pgWalUsage so that pgstat_flush_wal() can
* calculate how much pgWalUsage counters are increased by subtracting
* prevWalUsage from pgWalUsage.
*/
@@ -151,6 +144,28 @@ bool
pgstat_have_pending_wal(void)
{
return pgWalUsage.wal_records != prevWalUsage.wal_records ||
- WalStats.m_wal_write != 0 ||
- WalStats.m_wal_sync != 0;
+ PendingWalStats.wal_write != 0 ||
+ PendingWalStats.wal_sync != 0;
+}
+
+void
+pgstat_wal_reset_all_cb(TimestampTz ts)
+{
+ PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
+
+ LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
+ memset(&stats_shmem->stats, 0, sizeof(stats_shmem->stats));
+ stats_shmem->stats.stat_reset_timestamp = ts;
+ LWLockRelease(&stats_shmem->lock);
+}
+
+void
+pgstat_wal_snapshot_cb(void)
+{
+ PgStatShared_Wal *stats_shmem = &pgStatLocal.shmem->wal;
+
+ LWLockAcquire(&stats_shmem->lock, LW_SHARED);
+ memcpy(&pgStatLocal.snapshot.wal, &stats_shmem->stats,
+ sizeof(pgStatLocal.snapshot.wal));
+ LWLockRelease(&stats_shmem->lock);
}