@@ -1365,29 +1365,117 @@ pg_stat_us_to_ms(PgStat_Counter val_ms)
13651365return 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+
13681459Datum
13691460pg_stat_get_io (PG_FUNCTION_ARGS )
13701461{
13711462ReturnSetInfo * rsinfo ;
13721463PgStat_IO * backends_io_stats ;
1373- Datum reset_time ;
13741464
13751465InitMaterializedSRF (fcinfo ,0 );
13761466rsinfo = (ReturnSetInfo * )fcinfo -> resultinfo ;
13771467
13781468backends_io_stats = pgstat_fetch_stat_io ();
13791469
1380- reset_time = TimestampTzGetDatum (backends_io_stats -> stat_reset_timestamp );
1381-
13821470for (int bktype = 0 ;bktype < BACKEND_NUM_TYPES ;bktype ++ )
13831471{
1384- Datum bktype_desc = CStringGetTextDatum (GetBackendTypeDesc (bktype ));
13851472PgStat_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 */
13921480Assert (pgstat_bktype_io_stats_valid (bktype_stats ,bktype ));
13931481
@@ -1398,77 +1486,9 @@ pg_stat_get_io(PG_FUNCTION_ARGS)
13981486if (!pgstat_tracks_io_bktype (bktype ))
13991487continue ;
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
14741494return (Datum )0 ;