Skip to content

Commit ff7c40d

Browse files
committed
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
1 parent 08cdb07 commit ff7c40d

File tree

1 file changed

+97
-77
lines changed

1 file changed

+97
-77
lines changed

src/backend/utils/adt/pgstatfuncs.c

Lines changed: 97 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,29 +1365,117 @@ pg_stat_us_to_ms(PgStat_Counter val_ms)
13651365
return val_ms * (double) 0.001;
13661366
}
13671367

1368+
/*
1369+
* pg_stat_io_build_tuples
1370+
*
1371+
* Helper routine for pg_stat_get_io() filling a result tuplestore with one
1372+
* tuple for each object and each context supported by the caller, based on the
1373+
* contents of bktype_stats.
1374+
*/
1375+
static void
1376+
pg_stat_io_build_tuples(ReturnSetInfo *rsinfo,
1377+
PgStat_BktypeIO *bktype_stats,
1378+
BackendType bktype,
1379+
TimestampTz stat_reset_timestamp)
1380+
{
1381+
Datum bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype));
1382+
1383+
for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++)
1384+
{
1385+
const char *obj_name = pgstat_get_io_object_name(io_obj);
1386+
1387+
for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
1388+
{
1389+
const char *context_name = pgstat_get_io_context_name(io_context);
1390+
1391+
Datum values[IO_NUM_COLUMNS] = {0};
1392+
bool nulls[IO_NUM_COLUMNS] = {0};
1393+
1394+
/*
1395+
* Some combinations of BackendType, IOObject, and IOContext are
1396+
* not valid for any type of IOOp. In such cases, omit the entire
1397+
* row from the view.
1398+
*/
1399+
if (!pgstat_tracks_io_object(bktype, io_obj, io_context))
1400+
continue;
1401+
1402+
values[IO_COL_BACKEND_TYPE] = bktype_desc;
1403+
values[IO_COL_CONTEXT] = CStringGetTextDatum(context_name);
1404+
values[IO_COL_OBJECT] = CStringGetTextDatum(obj_name);
1405+
if (stat_reset_timestamp != 0)
1406+
values[IO_COL_RESET_TIME] = TimestampTzGetDatum(stat_reset_timestamp);
1407+
else
1408+
nulls[IO_COL_RESET_TIME] = true;
1409+
1410+
/*
1411+
* Hard-code this to the value of BLCKSZ for now. Future values
1412+
* could include XLOG_BLCKSZ, once WAL IO is tracked, and constant
1413+
* multipliers, once non-block-oriented IO (e.g. temporary file
1414+
* IO) is tracked.
1415+
*/
1416+
values[IO_COL_CONVERSION] = Int64GetDatum(BLCKSZ);
1417+
1418+
for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
1419+
{
1420+
int op_idx = pgstat_get_io_op_index(io_op);
1421+
int time_idx = pgstat_get_io_time_index(io_op);
1422+
1423+
/*
1424+
* Some combinations of BackendType and IOOp, of IOContext and
1425+
* IOOp, and of IOObject and IOOp are not tracked. Set these
1426+
* cells in the view NULL.
1427+
*/
1428+
if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op))
1429+
{
1430+
PgStat_Counter count =
1431+
bktype_stats->counts[io_obj][io_context][io_op];
1432+
1433+
values[op_idx] = Int64GetDatum(count);
1434+
}
1435+
else
1436+
nulls[op_idx] = true;
1437+
1438+
/* not every operation is timed */
1439+
if (time_idx == IO_COL_INVALID)
1440+
continue;
1441+
1442+
if (!nulls[op_idx])
1443+
{
1444+
PgStat_Counter time =
1445+
bktype_stats->times[io_obj][io_context][io_op];
1446+
1447+
values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time));
1448+
}
1449+
else
1450+
nulls[time_idx] = true;
1451+
}
1452+
1453+
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
1454+
values, nulls);
1455+
}
1456+
}
1457+
}
1458+
13681459
Datum
13691460
pg_stat_get_io(PG_FUNCTION_ARGS)
13701461
{
13711462
ReturnSetInfo *rsinfo;
13721463
PgStat_IO *backends_io_stats;
1373-
Datum reset_time;
13741464

13751465
InitMaterializedSRF(fcinfo, 0);
13761466
rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
13771467

13781468
backends_io_stats = pgstat_fetch_stat_io();
13791469

1380-
reset_time = TimestampTzGetDatum(backends_io_stats->stat_reset_timestamp);
1381-
13821470
for (int bktype = 0; bktype < BACKEND_NUM_TYPES; bktype++)
13831471
{
1384-
Datum bktype_desc = CStringGetTextDatum(GetBackendTypeDesc(bktype));
13851472
PgStat_BktypeIO *bktype_stats = &backends_io_stats->stats[bktype];
13861473

13871474
/*
13881475
* In Assert builds, we can afford an extra loop through all of the
1389-
* counters checking that only expected stats are non-zero, since it
1390-
* keeps the non-Assert code cleaner.
1476+
* counters (in pg_stat_io_build_tuples()), checking that only
1477+
* expected stats are non-zero, since it keeps the non-Assert code
1478+
* cleaner.
13911479
*/
13921480
Assert(pgstat_bktype_io_stats_valid(bktype_stats, bktype));
13931481

@@ -1398,77 +1486,9 @@ pg_stat_get_io(PG_FUNCTION_ARGS)
13981486
if (!pgstat_tracks_io_bktype(bktype))
13991487
continue;
14001488

1401-
for (int io_obj = 0; io_obj < IOOBJECT_NUM_TYPES; io_obj++)
1402-
{
1403-
const char *obj_name = pgstat_get_io_object_name(io_obj);
1404-
1405-
for (int io_context = 0; io_context < IOCONTEXT_NUM_TYPES; io_context++)
1406-
{
1407-
const char *context_name = pgstat_get_io_context_name(io_context);
1408-
1409-
Datum values[IO_NUM_COLUMNS] = {0};
1410-
bool nulls[IO_NUM_COLUMNS] = {0};
1411-
1412-
/*
1413-
* Some combinations of BackendType, IOObject, and IOContext
1414-
* are not valid for any type of IOOp. In such cases, omit the
1415-
* entire row from the view.
1416-
*/
1417-
if (!pgstat_tracks_io_object(bktype, io_obj, io_context))
1418-
continue;
1419-
1420-
values[IO_COL_BACKEND_TYPE] = bktype_desc;
1421-
values[IO_COL_CONTEXT] = CStringGetTextDatum(context_name);
1422-
values[IO_COL_OBJECT] = CStringGetTextDatum(obj_name);
1423-
values[IO_COL_RESET_TIME] = reset_time;
1424-
1425-
/*
1426-
* Hard-code this to the value of BLCKSZ for now. Future
1427-
* values could include XLOG_BLCKSZ, once WAL IO is tracked,
1428-
* and constant multipliers, once non-block-oriented IO (e.g.
1429-
* temporary file IO) is tracked.
1430-
*/
1431-
values[IO_COL_CONVERSION] = Int64GetDatum(BLCKSZ);
1432-
1433-
for (int io_op = 0; io_op < IOOP_NUM_TYPES; io_op++)
1434-
{
1435-
int op_idx = pgstat_get_io_op_index(io_op);
1436-
int time_idx = pgstat_get_io_time_index(io_op);
1437-
1438-
/*
1439-
* Some combinations of BackendType and IOOp, of IOContext
1440-
* and IOOp, and of IOObject and IOOp are not tracked. Set
1441-
* these cells in the view NULL.
1442-
*/
1443-
if (pgstat_tracks_io_op(bktype, io_obj, io_context, io_op))
1444-
{
1445-
PgStat_Counter count =
1446-
bktype_stats->counts[io_obj][io_context][io_op];
1447-
1448-
values[op_idx] = Int64GetDatum(count);
1449-
}
1450-
else
1451-
nulls[op_idx] = true;
1452-
1453-
/* not every operation is timed */
1454-
if (time_idx == IO_COL_INVALID)
1455-
continue;
1456-
1457-
if (!nulls[op_idx])
1458-
{
1459-
PgStat_Counter time =
1460-
bktype_stats->times[io_obj][io_context][io_op];
1461-
1462-
values[time_idx] = Float8GetDatum(pg_stat_us_to_ms(time));
1463-
}
1464-
else
1465-
nulls[time_idx] = true;
1466-
}
1467-
1468-
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
1469-
values, nulls);
1470-
}
1471-
}
1489+
/* save tuples with data from this PgStat_BktypeIO */
1490+
pg_stat_io_build_tuples(rsinfo, bktype_stats, bktype,
1491+
backends_io_stats->stat_reset_timestamp);
14721492
}
14731493

14741494
return (Datum) 0;

0 commit comments

Comments
 (0)