aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/pgstatfuncs.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2024-12-19 10:16:02 +0900
committerMichael Paquier <michael@paquier.xyz>2024-12-19 10:16:02 +0900
commitff7c40d7fd6a218f31fcf6f2c23c544c85934b24 (patch)
treeea63f1679dff45597091990f9e7abebdbb353bf7 /src/backend/utils/adt/pgstatfuncs.c
parent08cdb079d4a8a82c687321e9ffe0a3d3fbcc0551 (diff)
downloadpostgresql-ff7c40d7fd6a218f31fcf6f2c23c544c85934b24.tar.gz
postgresql-ff7c40d7fd6a218f31fcf6f2c23c544c85934b24.zip
Extract logic filling pg_stat_get_io()'s tuplestore into its own routine
This commit adds pg_stat_io_build_tuples(), a helper routine for pg_stat_get_io(), that fills its result tuplestore based on the contents of PgStat_BktypeIO. This will be used in a follow-up commit that uses the same structures as pg_stat_io for reporting, including the same object types and contexts, but for a different statistics kind. Author: Bertrand Drouvot, Michael Paquier Discussion: https://postgr.es/m/ZtXR+CtkEVVE/LHF@ip-10-97-1-34.eu-west-3.compute.internal
Diffstat (limited to 'src/backend/utils/adt/pgstatfuncs.c')
-rw-r--r--src/backend/utils/adt/pgstatfuncs.c174
1 files changed, 97 insertions, 77 deletions
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index cdf37403e9d..03dd8cd335a 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1365,29 +1365,117 @@ pg_stat_us_to_ms(PgStat_Counter val_ms)
return val_ms * (double) 0.001;
}
+/*
+ * pg_stat_io_build_tuples
+ *
+ * Helper routine for pg_stat_get_io() filling a result tuplestore with one
+ * tuple for each object and each context supported by the caller, based on the
+ * contents of bktype_stats.
+ */
+static void
+pg_stat_io_build_tuples(ReturnSetInfo *rsinfo,
+ PgStat_BktypeIO *bktype_stats,
+ BackendType bktype,
+ TimestampTz stat_reset_timestamp)
+{
+ Datum bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype));
+
+ for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++)
+ {
+ const char *obj_name = pgstat_get_io_object_name(io_obj);
+
+ for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
+ {
+ const char *context_name = pgstat_get_io_context_name(io_context);
+
+ Datum values[IO_NUM_COLUMNS] = {0};
+ bool nulls[IO_NUM_COLUMNS] = {0};
+
+ /*
+ * Some combinations of BackendType, IOObject, and IOContext are
+ * not valid for any type of IOOp. In such cases, omit the entire
+ * row from the view.
+ */
+ if (!pgstat_tracks_io_object(bktype, io_obj, io_context))
+ continue;
+
+ values[IO_COL_BACKEND_TYPE] = bktype_desc;
+ values[IO_COL_CONTEXT] = CStringGetTextDatum(context_name);
+ values[IO_COL_OBJECT] = CStringGetTextDatum(obj_name);
+ if (stat_reset_timestamp != 0)
+ values[IO_COL_RESET_TIME] = TimestampTzGetDatum(stat_reset_timestamp);
+ else
+ nulls[IO_COL_RESET_TIME] = true;
+
+ /*
+ * Hard-code this to the value of BLCKSZ for now. Future values
+ * could include XLOG_BLCKSZ, once WAL IO is tracked, and constant
+ * multipliers, once non-block-oriented IO (e.g. temporary file
+ * IO) is tracked.
+ */
+ values[IO_COL_CONVERSION] = Int64GetDatum(BLCKSZ);
+
+ for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
+ {
+ int op_idx = pgstat_get_io_op_index(io_op);
+ int time_idx = pgstat_get_io_time_index(io_op);
+
+ /*
+ * Some combinations of BackendType and IOOp, of IOContext and
+ * IOOp, and of IOObject and IOOp are not tracked. Set these
+ * cells in the view NULL.
+ */
+ if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op))
+ {
+ PgStat_Counter count =
+ bktype_stats->counts[io_obj][io_context][io_op];
+
+ values[op_idx] = Int64GetDatum(count);
+ }
+ else
+ nulls[op_idx] = true;
+
+ /* not every operation is timed */
+ if (time_idx == IO_COL_INVALID)
+ continue;
+
+ if (!nulls[op_idx])
+ {
+ PgStat_Counter time =
+ bktype_stats->times[io_obj][io_context][io_op];
+
+ values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time));
+ }
+ else
+ nulls[time_idx] = true;
+ }
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
+ }
+ }
+}
+
Datum
pg_stat_get_io(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo;
PgStat_IO *backends_io_stats;
- Datum reset_time;
InitMaterializedSRF(fcinfo, 0);
rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
backends_io_stats = pgstat_fetch_stat_io();
- reset_time = TimestampTzGetDatum(backends_io_stats->stat_reset_timestamp);
-
for (int bktype = 0; bktype < BACKEND_NUM_TYPES; bktype++)
{
- Datum bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype));
PgStat_BktypeIO *bktype_stats = &backends_io_stats->stats[bktype];
/*
* In Assert builds, we can afford an extra loop through all of the
- * counters checking that only expected stats are non-zero, since it
- * keeps the non-Assert code cleaner.
+ * counters (in pg_stat_io_build_tuples()), checking that only
+ * expected stats are non-zero, since it keeps the non-Assert code
+ * cleaner.
*/
Assert(pgstat_bktype_io_stats_valid(bktype_stats, bktype));
@@ -1398,77 +1486,9 @@ pg_stat_get_io(PG_FUNCTION_ARGS)
if (!pgstat_tracks_io_bktype(bktype))
continue;
- for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++)
- {
- const char *obj_name = pgstat_get_io_object_name(io_obj);
-
- for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
- {
- const char *context_name = pgstat_get_io_context_name(io_context);
-
- Datum values[IO_NUM_COLUMNS] = {0};
- bool nulls[IO_NUM_COLUMNS] = {0};
-
- /*
- * Some combinations of BackendType, IOObject, and IOContext
- * are not valid for any type of IOOp. In such cases, omit the
- * entire row from the view.
- */
- if (!pgstat_tracks_io_object(bktype, io_obj, io_context))
- continue;
-
- values[IO_COL_BACKEND_TYPE] = bktype_desc;
- values[IO_COL_CONTEXT] = CStringGetTextDatum(context_name);
- values[IO_COL_OBJECT] = CStringGetTextDatum(obj_name);
- values[IO_COL_RESET_TIME] = reset_time;
-
- /*
- * Hard-code this to the value of BLCKSZ for now. Future
- * values could include XLOG_BLCKSZ, once WAL IO is tracked,
- * and constant multipliers, once non-block-oriented IO (e.g.
- * temporary file IO) is tracked.
- */
- values[IO_COL_CONVERSION] = Int64GetDatum(BLCKSZ);
-
- for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
- {
- int op_idx = pgstat_get_io_op_index(io_op);
- int time_idx = pgstat_get_io_time_index(io_op);
-
- /*
- * Some combinations of BackendType and IOOp, of IOContext
- * and IOOp, and of IOObject and IOOp are not tracked. Set
- * these cells in the view NULL.
- */
- if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op))
- {
- PgStat_Counter count =
- bktype_stats->counts[io_obj][io_context][io_op];
-
- values[op_idx] = Int64GetDatum(count);
- }
- else
- nulls[op_idx] = true;
-
- /* not every operation is timed */
- if (time_idx == IO_COL_INVALID)
- continue;
-
- if (!nulls[op_idx])
- {
- PgStat_Counter time =
- bktype_stats->times[io_obj][io_context][io_op];
-
- values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time));
- }
- else
- nulls[time_idx] = true;
- }
-
- tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
- values, nulls);
- }
- }
+ /* save tuples with data from this PgStat_BktypeIO */
+ pg_stat_io_build_tuples(rsinfo, bktype_stats, bktype,
+ backends_io_stats->stat_reset_timestamp);
}
return (Datum) 0;