Coverage Report

Created: 2025-10-09 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}