/src/postgres/src/backend/access/transam/xlogstats.c
Line | Count | Source |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * xlogstats.c |
4 | | * Functions for WAL Statitstics |
5 | | * |
6 | | * Copyright (c) 2022-2025, 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 | | XLogRecGetLen(XLogReaderState *record, uint32 *rec_len, |
23 | | uint32 *fpi_len) |
24 | 0 | { |
25 | 0 | 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 | 0 | *fpi_len = 0; |
34 | 0 | for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++) |
35 | 0 | { |
36 | 0 | if (!XLogRecHasBlockRef(record, block_id)) |
37 | 0 | continue; |
38 | | |
39 | 0 | if (XLogRecHasBlockImage(record, block_id)) |
40 | 0 | *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len; |
41 | 0 | } |
42 | | |
43 | | /* |
44 | | * Calculate the length of the record as the total length - the length of |
45 | | * all the block images. |
46 | | */ |
47 | 0 | *rec_len = XLogRecGetTotalLen(record) - *fpi_len; |
48 | 0 | } |
49 | | |
50 | | /* |
51 | | * Store per-rmgr and per-record statistics for a given record. |
52 | | */ |
53 | | void |
54 | | XLogRecStoreStats(XLogStats *stats, XLogReaderState *record) |
55 | 0 | { |
56 | 0 | RmgrId rmid; |
57 | 0 | uint8 recid; |
58 | 0 | uint32 rec_len; |
59 | 0 | uint32 fpi_len; |
60 | |
|
61 | 0 | Assert(stats != NULL && record != NULL); |
62 | |
|
63 | 0 | stats->count++; |
64 | |
|
65 | 0 | rmid = XLogRecGetRmid(record); |
66 | |
|
67 | 0 | XLogRecGetLen(record, &rec_len, &fpi_len); |
68 | | |
69 | | /* Update per-rmgr statistics */ |
70 | |
|
71 | 0 | stats->rmgr_stats[rmid].count++; |
72 | 0 | stats->rmgr_stats[rmid].rec_len += rec_len; |
73 | 0 | 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 | 0 | 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 | 0 | if (rmid == RM_XACT_ID) |
91 | 0 | recid &= 0x07; |
92 | |
|
93 | 0 | stats->record_stats[rmid][recid].count++; |
94 | 0 | stats->record_stats[rmid][recid].rec_len += rec_len; |
95 | 0 | stats->record_stats[rmid][recid].fpi_len += fpi_len; |
96 | 0 | } |