/*------------------------------------------------------------------------- * * xlogstats.c * Functions for WAL Statitstics * * Copyright (c) 2022-2023, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/access/transam/xlogstats.c * *------------------------------------------------------------------------- */ #include "postgres.h" #include "access/xlogreader.h" #include "access/xlogstats.h" /* * Calculate the size of a record, split into !FPI and FPI parts. */ void XLogRecGetLen(XLogReaderState *record, uint32 *rec_len, uint32 *fpi_len) { int block_id; /* * Calculate the amount of FPI data in the record. * * XXX: We peek into xlogreader's private decoded backup blocks for the * bimg_len indicating the length of FPI data. */ *fpi_len = 0; for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++) { if (!XLogRecHasBlockRef(record, block_id)) continue; if (XLogRecHasBlockImage(record, block_id)) *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len; } /* * Calculate the length of the record as the total length - the length of * all the block images. */ *rec_len = XLogRecGetTotalLen(record) - *fpi_len; } /* * Store per-rmgr and per-record statistics for a given record. */ void XLogRecStoreStats(XLogStats *stats, XLogReaderState *record) { RmgrId rmid; uint8 recid; uint32 rec_len; uint32 fpi_len; Assert(stats != NULL && record != NULL); stats->count++; rmid = XLogRecGetRmid(record); XLogRecGetLen(record, &rec_len, &fpi_len); /* Update per-rmgr statistics */ stats->rmgr_stats[rmid].count++; stats->rmgr_stats[rmid].rec_len += rec_len; stats->rmgr_stats[rmid].fpi_len += fpi_len; /* * Update per-record statistics, where the record is identified by a * combination of the RmgrId and the four bits of the xl_info field that * are the rmgr's domain (resulting in sixteen possible entries per * RmgrId). */ recid = XLogRecGetInfo(record) >> 4; /* * XACT records need to be handled differently. Those records use the * first bit of those four bits for an optional flag variable and the * following three bits for the opcode. We filter opcode out of xl_info * and use it as the identifier of the record. */ if (rmid == RM_XACT_ID) recid &= 0x07; stats->record_stats[rmid][recid].count++; stats->record_stats[rmid][recid].rec_len += rec_len; stats->record_stats[rmid][recid].fpi_len += fpi_len; }