1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-29 16:21:20 +03:00

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
This commit is contained in:
Michael Paquier 2024-12-19 10:16:02 +09:00
parent 08cdb079d4
commit ff7c40d7fd

View File

@ -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;