Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * xlogstats.c 4 : * Functions for WAL Statitstics 5 : * 6 : * Copyright (c) 2022-2024, PostgreSQL Global Development Group 7 : * 8 : * IDENTIFICATION 9 : * src/backend/access/transam/xlogstats.c 10 : * 11 : *------------------------------------------------------------------------- 12 : */ 13 : #include "postgres.h" 14 : 15 : #include "access/xlogreader.h" 16 : #include "access/xlogstats.h" 17 : 18 : /* 19 : * Calculate the size of a record, split into !FPI and FPI parts. 20 : */ 21 : void 22 28 : XLogRecGetLen(XLogReaderState *record, uint32 *rec_len, 23 : uint32 *fpi_len) 24 : { 25 : int block_id; 26 : 27 : /* 28 : * Calculate the amount of FPI data in the record. 29 : * 30 : * XXX: We peek into xlogreader's private decoded backup blocks for the 31 : * bimg_len indicating the length of FPI data. 32 : */ 33 28 : *fpi_len = 0; 34 48 : for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++) 35 : { 36 20 : if (!XLogRecHasBlockRef(record, block_id)) 37 0 : continue; 38 : 39 20 : if (XLogRecHasBlockImage(record, block_id)) 40 0 : *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len; 41 : } 42 : 43 : /* 44 : * Calculate the length of the record as the total length - the length of 45 : * all the block images. 46 : */ 47 28 : *rec_len = XLogRecGetTotalLen(record) - *fpi_len; 48 28 : } 49 : 50 : /* 51 : * Store per-rmgr and per-record statistics for a given record. 52 : */ 53 : void 54 28 : XLogRecStoreStats(XLogStats *stats, XLogReaderState *record) 55 : { 56 : RmgrId rmid; 57 : uint8 recid; 58 : uint32 rec_len; 59 : uint32 fpi_len; 60 : 61 : Assert(stats != NULL && record != NULL); 62 : 63 28 : stats->count++; 64 : 65 28 : rmid = XLogRecGetRmid(record); 66 : 67 28 : XLogRecGetLen(record, &rec_len, &fpi_len); 68 : 69 : /* Update per-rmgr statistics */ 70 : 71 28 : stats->rmgr_stats[rmid].count++; 72 28 : stats->rmgr_stats[rmid].rec_len += rec_len; 73 28 : stats->rmgr_stats[rmid].fpi_len += fpi_len; 74 : 75 : /* 76 : * Update per-record statistics, where the record is identified by a 77 : * combination of the RmgrId and the four bits of the xl_info field that 78 : * are the rmgr's domain (resulting in sixteen possible entries per 79 : * RmgrId). 80 : */ 81 : 82 28 : recid = XLogRecGetInfo(record) >> 4; 83 : 84 : /* 85 : * XACT records need to be handled differently. Those records use the 86 : * first bit of those four bits for an optional flag variable and the 87 : * following three bits for the opcode. We filter opcode out of xl_info 88 : * and use it as the identifier of the record. 89 : */ 90 28 : if (rmid == RM_XACT_ID) 91 8 : recid &= 0x07; 92 : 93 28 : stats->record_stats[rmid][recid].count++; 94 28 : stats->record_stats[rmid][recid].rec_len += rec_len; 95 28 : stats->record_stats[rmid][recid].fpi_len += fpi_len; 96 28 : }