summaryrefslogtreecommitdiffstats
path: root/src/backend/utils/activity/pgstat_slru.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:46:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:46:48 +0000
commit311bcfc6b3acdd6fd152798c7f287ddf74fa2a98 (patch)
tree0ec307299b1dada3701e42f4ca6eda57d708261e /src/backend/utils/activity/pgstat_slru.c
parentInitial commit. (diff)
downloadpostgresql-15-upstream.tar.xz
postgresql-15-upstream.zip
Adding upstream version 15.4.upstream/15.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/backend/utils/activity/pgstat_slru.c')
-rw-r--r--src/backend/utils/activity/pgstat_slru.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/src/backend/utils/activity/pgstat_slru.c b/src/backend/utils/activity/pgstat_slru.c
new file mode 100644
index 0000000..28ef736
--- /dev/null
+++ b/src/backend/utils/activity/pgstat_slru.c
@@ -0,0 +1,248 @@
+/* -------------------------------------------------------------------------
+ *
+ * pgstat_slru.c
+ * Implementation of SLRU statistics.
+ *
+ * This file contains the implementation of SLRU statistics. It is kept
+ * separate from pgstat.c to enforce the line between the statistics access /
+ * storage implementation and the details about individual types of
+ * statistics.
+ *
+ * Copyright (c) 2001-2022, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ * src/backend/utils/activity/pgstat_slru.c
+ * -------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "utils/pgstat_internal.h"
+#include "utils/timestamp.h"
+
+
+static inline PgStat_SLRUStats *get_slru_entry(int slru_idx);
+static void pgstat_reset_slru_counter_internal(int index, TimestampTz ts);
+
+
+/*
+ * SLRU statistics counts waiting to be flushed out. We assume this variable
+ * inits to zeroes. Entries are one-to-one with slru_names[]. Changes of
+ * SLRU counters are reported within critical sections so we use static memory
+ * in order to avoid memory allocation.
+ */
+static PgStat_SLRUStats pending_SLRUStats[SLRU_NUM_ELEMENTS];
+bool have_slrustats = false;
+
+
+/*
+ * Reset counters for a single SLRU.
+ *
+ * Permission checking for this function is managed through the normal
+ * GRANT system.
+ */
+void
+pgstat_reset_slru(const char *name)
+{
+ TimestampTz ts = GetCurrentTimestamp();
+
+ AssertArg(name != NULL);
+
+ pgstat_reset_slru_counter_internal(pgstat_get_slru_index(name), ts);
+}
+
+/*
+ * SLRU statistics count accumulation functions --- called from slru.c
+ */
+
+void
+pgstat_count_slru_page_zeroed(int slru_idx)
+{
+ get_slru_entry(slru_idx)->blocks_zeroed += 1;
+}
+
+void
+pgstat_count_slru_page_hit(int slru_idx)
+{
+ get_slru_entry(slru_idx)->blocks_hit += 1;
+}
+
+void
+pgstat_count_slru_page_exists(int slru_idx)
+{
+ get_slru_entry(slru_idx)->blocks_exists += 1;
+}
+
+void
+pgstat_count_slru_page_read(int slru_idx)
+{
+ get_slru_entry(slru_idx)->blocks_read += 1;
+}
+
+void
+pgstat_count_slru_page_written(int slru_idx)
+{
+ get_slru_entry(slru_idx)->blocks_written += 1;
+}
+
+void
+pgstat_count_slru_flush(int slru_idx)
+{
+ get_slru_entry(slru_idx)->flush += 1;
+}
+
+void
+pgstat_count_slru_truncate(int slru_idx)
+{
+ get_slru_entry(slru_idx)->truncate += 1;
+}
+
+/*
+ * Support function for the SQL-callable pgstat* functions. Returns
+ * a pointer to the slru statistics struct.
+ */
+PgStat_SLRUStats *
+pgstat_fetch_slru(void)
+{
+ pgstat_snapshot_fixed(PGSTAT_KIND_SLRU);
+
+ return pgStatLocal.snapshot.slru;
+}
+
+/*
+ * Returns SLRU name for an index. The index may be above SLRU_NUM_ELEMENTS,
+ * in which case this returns NULL. This allows writing code that does not
+ * know the number of entries in advance.
+ */
+const char *
+pgstat_get_slru_name(int slru_idx)
+{
+ if (slru_idx < 0 || slru_idx >= SLRU_NUM_ELEMENTS)
+ return NULL;
+
+ return slru_names[slru_idx];
+}
+
+/*
+ * Determine index of entry for a SLRU with a given name. If there's no exact
+ * match, returns index of the last "other" entry used for SLRUs defined in
+ * external projects.
+ */
+int
+pgstat_get_slru_index(const char *name)
+{
+ int i;
+
+ for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
+ {
+ if (strcmp(slru_names[i], name) == 0)
+ return i;
+ }
+
+ /* return index of the last entry (which is the "other" one) */
+ return (SLRU_NUM_ELEMENTS - 1);
+}
+
+/*
+ * Flush out locally pending SLRU stats entries
+ *
+ * If nowait is true, this function returns false on lock failure. Otherwise
+ * this function always returns true.
+ *
+ * If nowait is true, this function returns true if the lock could not be
+ * acquired. Otherwise return false.
+ */
+bool
+pgstat_slru_flush(bool nowait)
+{
+ PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
+ int i;
+
+ if (!have_slrustats)
+ return false;
+
+ if (!nowait)
+ LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
+ else if (!LWLockConditionalAcquire(&stats_shmem->lock, LW_EXCLUSIVE))
+ return true;
+
+ for (i = 0; i < SLRU_NUM_ELEMENTS; i++)
+ {
+ PgStat_SLRUStats *sharedent = &stats_shmem->stats[i];
+ PgStat_SLRUStats *pendingent = &pending_SLRUStats[i];
+
+#define SLRU_ACC(fld) sharedent->fld += pendingent->fld
+ SLRU_ACC(blocks_zeroed);
+ SLRU_ACC(blocks_hit);
+ SLRU_ACC(blocks_read);
+ SLRU_ACC(blocks_written);
+ SLRU_ACC(blocks_exists);
+ SLRU_ACC(flush);
+ SLRU_ACC(truncate);
+#undef SLRU_ACC
+ }
+
+ /* done, clear the pending entry */
+ MemSet(pending_SLRUStats, 0, sizeof(pending_SLRUStats));
+
+ LWLockRelease(&stats_shmem->lock);
+
+ have_slrustats = false;
+
+ return false;
+}
+
+void
+pgstat_slru_reset_all_cb(TimestampTz ts)
+{
+ for (int i = 0; i < SLRU_NUM_ELEMENTS; i++)
+ pgstat_reset_slru_counter_internal(i, ts);
+}
+
+void
+pgstat_slru_snapshot_cb(void)
+{
+ PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
+
+ LWLockAcquire(&stats_shmem->lock, LW_SHARED);
+
+ memcpy(pgStatLocal.snapshot.slru, &stats_shmem->stats,
+ sizeof(stats_shmem->stats));
+
+ LWLockRelease(&stats_shmem->lock);
+}
+
+/*
+ * Returns pointer to entry with counters for given SLRU (based on the name
+ * stored in SlruCtl as lwlock tranche name).
+ */
+static inline PgStat_SLRUStats *
+get_slru_entry(int slru_idx)
+{
+ pgstat_assert_is_up();
+
+ /*
+ * The postmaster should never register any SLRU statistics counts; if it
+ * did, the counts would be duplicated into child processes via fork().
+ */
+ Assert(IsUnderPostmaster || !IsPostmasterEnvironment);
+
+ Assert((slru_idx >= 0) && (slru_idx < SLRU_NUM_ELEMENTS));
+
+ have_slrustats = true;
+
+ return &pending_SLRUStats[slru_idx];
+}
+
+static void
+pgstat_reset_slru_counter_internal(int index, TimestampTz ts)
+{
+ PgStatShared_SLRU *stats_shmem = &pgStatLocal.shmem->slru;
+
+ LWLockAcquire(&stats_shmem->lock, LW_EXCLUSIVE);
+
+ memset(&stats_shmem->stats[index], 0, sizeof(PgStat_SLRUStats));
+ stats_shmem->stats[index].stat_reset_timestamp = ts;
+
+ LWLockRelease(&stats_shmem->lock);
+}