Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7d8219a

Browse files
Show more detail in heapam rmgr descriptions.
Add helper functions that output arrays in a standard format, and use the functions inside heapdesc routines. This allows tools like pg_walinspect to show a detailed description of the page offset number arrays for records like PRUNE and VACUUM (unless there was an FPI). Also document the conventions that desc routines should follow. Only the heapdesc routines follow the conventions for now, so they're just guidelines for the time being. Based on a suggestion from Andres Freund. Author: Melanie Plageman <melanieplageman@gmail.com> Reviewed-By: Peter Geoghegan <pg@bowt.ie> Discussion: https://postgr.es/m/flat/20230109215842.fktuhesvayno6o4g%40awork3.anarazel.de
1 parent 76c111a commit 7d8219a

File tree

7 files changed

+247
-40
lines changed

7 files changed

+247
-40
lines changed

doc/src/sgml/pgwalinspect.sgml

+11-11
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,19 @@
7171
after the <replaceable>in_lsn</replaceable> argument. For
7272
example:
7373
<screen>
74-
postgres=# SELECT * FROM pg_get_wal_record_info('0/1E826E98');
75-
-[ RECORD 1 ]----+----------------------------------------------------
76-
start_lsn | 0/1E826F20
77-
end_lsn | 0/1E826F60
78-
prev_lsn | 0/1E826C80
74+
postgres=# SELECT * FROM pg_get_wal_record_info('0/E84F5E8');
75+
-[ RECORD 1 ]----+--------------------------------------------------
76+
start_lsn | 0/E84F5E8
77+
end_lsn | 0/E84F620
78+
prev_lsn | 0/E84F5A8
7979
xid | 0
8080
resource_manager | Heap2
81-
record_type | PRUNE
82-
record_length | 58
83-
main_data_length | 8
81+
record_type | VACUUM
82+
record_length | 50
83+
main_data_length | 2
8484
fpi_length | 0
85-
description | snapshotConflictHorizon 33748 nredirected 0 ndead 2
86-
block_ref | blkref #0: rel 1663/5/60221 fork main blk 2
85+
description | nunused: 1, unused: [ 22 ]
86+
block_ref | blkref #0: rel 1663/16389/20884 fork main blk 126
8787
</screen>
8888
</para>
8989
<para>
@@ -144,7 +144,7 @@ block_ref |
144144
references. Returns one row per block reference per WAL record.
145145
For example:
146146
<screen>
147-
postgres=# SELECT * FROM pg_get_wal_block_info('0/10E9D80', '0/10E9DC0') LIMIT 1;
147+
postgres=# SELECT * FROM pg_get_wal_block_info('0/10E9D80', '0/10E9DC0');
148148
-[ RECORD 1 ]-----+-----------------------------------
149149
start_lsn | 0/10E9D80
150150
end_lsn | 0/10E9DC0

src/backend/access/rmgrdesc/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ OBJS = \
2323
nbtdesc.o \
2424
relmapdesc.o \
2525
replorigindesc.o \
26+
rmgrdesc_utils.o \
2627
seqdesc.o \
2728
smgrdesc.o \
2829
spgdesc.o \

src/backend/access/rmgrdesc/heapdesc.c

+127-28
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,52 @@
1515
#include "postgres.h"
1616

1717
#include "access/heapam_xlog.h"
18+
#include "access/rmgrdesc_utils.h"
1819

1920
static void
2021
out_infobits(StringInfo buf, uint8 infobits)
2122
{
23+
if ((infobits & XLHL_XMAX_IS_MULTI) == 0 &&
24+
(infobits & XLHL_XMAX_LOCK_ONLY) == 0 &&
25+
(infobits & XLHL_XMAX_EXCL_LOCK) == 0 &&
26+
(infobits & XLHL_XMAX_KEYSHR_LOCK) == 0 &&
27+
(infobits & XLHL_KEYS_UPDATED) == 0)
28+
return;
29+
30+
appendStringInfoString(buf, ", infobits: [");
31+
2232
if (infobits & XLHL_XMAX_IS_MULTI)
23-
appendStringInfoString(buf, "IS_MULTI ");
33+
appendStringInfoString(buf, " IS_MULTI");
2434
if (infobits & XLHL_XMAX_LOCK_ONLY)
25-
appendStringInfoString(buf, "LOCK_ONLY ");
35+
appendStringInfoString(buf, ", LOCK_ONLY");
2636
if (infobits & XLHL_XMAX_EXCL_LOCK)
27-
appendStringInfoString(buf, "EXCL_LOCK ");
37+
appendStringInfoString(buf, ", EXCL_LOCK");
2838
if (infobits & XLHL_XMAX_KEYSHR_LOCK)
29-
appendStringInfoString(buf, "KEYSHR_LOCK ");
39+
appendStringInfoString(buf, ", KEYSHR_LOCK");
3040
if (infobits & XLHL_KEYS_UPDATED)
31-
appendStringInfoString(buf, "KEYS_UPDATED ");
41+
appendStringInfoString(buf, ", KEYS_UPDATED");
42+
43+
appendStringInfoString(buf, " ]");
44+
}
45+
46+
static void
47+
plan_elem_desc(StringInfo buf, void *plan, void *data)
48+
{
49+
xl_heap_freeze_plan *new_plan = (xl_heap_freeze_plan *) plan;
50+
OffsetNumber **offsets = data;
51+
52+
appendStringInfo(buf, "{ xmax: %u, infomask: %u, infomask2: %u, ntuples: %u",
53+
new_plan->xmax,
54+
new_plan->t_infomask, new_plan->t_infomask2,
55+
new_plan->ntuples);
56+
57+
appendStringInfoString(buf, ", offsets:");
58+
array_desc(buf, *offsets, sizeof(OffsetNumber), new_plan->ntuples,
59+
&offset_elem_desc, NULL);
60+
61+
*offsets += new_plan->ntuples;
62+
63+
appendStringInfo(buf, " }");
3264
}
3365

3466
void
@@ -42,14 +74,15 @@ heap_desc(StringInfo buf, XLogReaderState *record)
4274
{
4375
xl_heap_insert *xlrec = (xl_heap_insert *) rec;
4476

45-
appendStringInfo(buf, "off %u flags 0x%02X", xlrec->offnum,
77+
appendStringInfo(buf, "off: %u, flags: 0x%02X",
78+
xlrec->offnum,
4679
xlrec->flags);
4780
}
4881
else if (info == XLOG_HEAP_DELETE)
4982
{
5083
xl_heap_delete *xlrec = (xl_heap_delete *) rec;
5184

52-
appendStringInfo(buf, "off %u flags 0x%02X ",
85+
appendStringInfo(buf, "off: %u, flags: 0x%02X",
5386
xlrec->offnum,
5487
xlrec->flags);
5588
out_infobits(buf, xlrec->infobits_set);
@@ -58,62 +91,66 @@ heap_desc(StringInfo buf, XLogReaderState *record)
5891
{
5992
xl_heap_update *xlrec = (xl_heap_update *) rec;
6093

61-
appendStringInfo(buf, "off %u xmax %u flags 0x%02X ",
94+
appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
6295
xlrec->old_offnum,
6396
xlrec->old_xmax,
6497
xlrec->flags);
6598
out_infobits(buf, xlrec->old_infobits_set);
66-
appendStringInfo(buf, "; new off %u xmax %u",
99+
appendStringInfo(buf, ", new off: %u, xmax %u",
67100
xlrec->new_offnum,
68101
xlrec->new_xmax);
69102
}
70103
else if (info == XLOG_HEAP_HOT_UPDATE)
71104
{
72105
xl_heap_update *xlrec = (xl_heap_update *) rec;
73106

74-
appendStringInfo(buf, "off %u xmax %u flags 0x%02X ",
107+
appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
75108
xlrec->old_offnum,
76109
xlrec->old_xmax,
77110
xlrec->flags);
78111
out_infobits(buf, xlrec->old_infobits_set);
79-
appendStringInfo(buf, "; new off %u xmax %u",
112+
appendStringInfo(buf, ", new off: %u, xmax: %u",
80113
xlrec->new_offnum,
81114
xlrec->new_xmax);
82115
}
83116
else if (info == XLOG_HEAP_TRUNCATE)
84117
{
85118
xl_heap_truncate *xlrec = (xl_heap_truncate *) rec;
86-
int i;
87119

120+
appendStringInfoString(buf, "flags: [");
88121
if (xlrec->flags & XLH_TRUNCATE_CASCADE)
89-
appendStringInfoString(buf, "cascade ");
122+
appendStringInfoString(buf, " CASCADE");
90123
if (xlrec->flags & XLH_TRUNCATE_RESTART_SEQS)
91-
appendStringInfoString(buf, "restart_seqs ");
92-
appendStringInfo(buf, "nrelids %u relids", xlrec->nrelids);
93-
for (i = 0; i < xlrec->nrelids; i++)
94-
appendStringInfo(buf, " %u", xlrec->relids[i]);
124+
appendStringInfoString(buf, ", RESTART_SEQS");
125+
appendStringInfoString(buf, " ]");
126+
127+
appendStringInfo(buf, ", nrelids: %u", xlrec->nrelids);
128+
appendStringInfoString(buf, ", relids:");
129+
array_desc(buf, xlrec->relids, sizeof(Oid), xlrec->nrelids,
130+
&relid_desc, NULL);
95131
}
96132
else if (info == XLOG_HEAP_CONFIRM)
97133
{
98134
xl_heap_confirm *xlrec = (xl_heap_confirm *) rec;
99135

100-
appendStringInfo(buf, "off %u", xlrec->offnum);
136+
appendStringInfo(buf, "off: %u", xlrec->offnum);
101137
}
102138
else if (info == XLOG_HEAP_LOCK)
103139
{
104140
xl_heap_lock *xlrec = (xl_heap_lock *) rec;
105141

106-
appendStringInfo(buf, "off %u: xid %u: flags 0x%02X ",
142+
appendStringInfo(buf, "off: %u, xid: %u, flags: 0x%02X",
107143
xlrec->offnum, xlrec->locking_xid, xlrec->flags);
108144
out_infobits(buf, xlrec->infobits_set);
109145
}
110146
else if (info == XLOG_HEAP_INPLACE)
111147
{
112148
xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
113149

114-
appendStringInfo(buf, "off %u", xlrec->offnum);
150+
appendStringInfo(buf, "off: %u", xlrec->offnum);
115151
}
116152
}
153+
117154
void
118155
heap2_desc(StringInfo buf, XLogReaderState *record)
119156
{
@@ -125,57 +162,119 @@ heap2_desc(StringInfo buf, XLogReaderState *record)
125162
{
126163
xl_heap_prune *xlrec = (xl_heap_prune *) rec;
127164

128-
appendStringInfo(buf, "snapshotConflictHorizon %u nredirected %u ndead %u",
165+
appendStringInfo(buf, "snapshotConflictHorizon: %u, nredirected: %u, ndead: %u",
129166
xlrec->snapshotConflictHorizon,
130167
xlrec->nredirected,
131168
xlrec->ndead);
169+
170+
if (!XLogRecHasBlockImage(record, 0))
171+
{
172+
OffsetNumber *end;
173+
OffsetNumber *redirected;
174+
OffsetNumber *nowdead;
175+
OffsetNumber *nowunused;
176+
int nredirected;
177+
int nunused;
178+
Size datalen;
179+
180+
redirected = (OffsetNumber *) XLogRecGetBlockData(record, 0,
181+
&datalen);
182+
183+
nredirected = xlrec->nredirected;
184+
end = (OffsetNumber *) ((char *) redirected + datalen);
185+
nowdead = redirected + (nredirected * 2);
186+
nowunused = nowdead + xlrec->ndead;
187+
nunused = (end - nowunused);
188+
Assert(nunused >= 0);
189+
190+
appendStringInfo(buf, ", nunused: %u", nunused);
191+
192+
appendStringInfoString(buf, ", redirected:");
193+
array_desc(buf, redirected, sizeof(OffsetNumber) * 2,
194+
nredirected, &redirect_elem_desc, NULL);
195+
appendStringInfoString(buf, ", dead:");
196+
array_desc(buf, nowdead, sizeof(OffsetNumber), xlrec->ndead,
197+
&offset_elem_desc, NULL);
198+
appendStringInfoString(buf, ", unused:");
199+
array_desc(buf, nowunused, sizeof(OffsetNumber), nunused,
200+
&offset_elem_desc, NULL);
201+
}
132202
}
133203
else if (info == XLOG_HEAP2_VACUUM)
134204
{
135205
xl_heap_vacuum *xlrec = (xl_heap_vacuum *) rec;
136206

137-
appendStringInfo(buf, "nunused %u", xlrec->nunused);
207+
appendStringInfo(buf, "nunused: %u", xlrec->nunused);
208+
209+
if (!XLogRecHasBlockImage(record, 0))
210+
{
211+
OffsetNumber *nowunused;
212+
213+
nowunused = (OffsetNumber *) XLogRecGetBlockData(record, 0, NULL);
214+
215+
appendStringInfoString(buf, ", unused:");
216+
array_desc(buf, nowunused, sizeof(OffsetNumber), xlrec->nunused,
217+
&offset_elem_desc, NULL);
218+
}
138219
}
139220
else if (info == XLOG_HEAP2_FREEZE_PAGE)
140221
{
141222
xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec;
142223

143-
appendStringInfo(buf, "snapshotConflictHorizon %u nplans %u",
224+
appendStringInfo(buf, "snapshotConflictHorizon: %u, nplans: %u",
144225
xlrec->snapshotConflictHorizon, xlrec->nplans);
226+
227+
if (!XLogRecHasBlockImage(record, 0))
228+
{
229+
xl_heap_freeze_plan *plans;
230+
OffsetNumber *offsets;
231+
232+
plans = (xl_heap_freeze_plan *) XLogRecGetBlockData(record, 0, NULL);
233+
offsets = (OffsetNumber *) &plans[xlrec->nplans];
234+
appendStringInfoString(buf, ", plans:");
235+
array_desc(buf, plans, sizeof(xl_heap_freeze_plan), xlrec->nplans,
236+
&plan_elem_desc, &offsets);
237+
}
145238
}
146239
else if (info == XLOG_HEAP2_VISIBLE)
147240
{
148241
xl_heap_visible *xlrec = (xl_heap_visible *) rec;
149242

150-
appendStringInfo(buf, "snapshotConflictHorizon %u flags 0x%02X",
243+
appendStringInfo(buf, "snapshotConflictHorizon: %u, flags: 0x%02X",
151244
xlrec->snapshotConflictHorizon, xlrec->flags);
152245
}
153246
else if (info == XLOG_HEAP2_MULTI_INSERT)
154247
{
155248
xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
249+
bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0;
156250

157-
appendStringInfo(buf, "%d tuples flags 0x%02X", xlrec->ntuples,
251+
appendStringInfo(buf, "ntuples: %d, flags: 0x%02X", xlrec->ntuples,
158252
xlrec->flags);
253+
254+
appendStringInfoString(buf, ", offsets:");
255+
if (!XLogRecHasBlockImage(record, 0) && !isinit)
256+
array_desc(buf, xlrec->offsets, sizeof(OffsetNumber),
257+
xlrec->ntuples, &offset_elem_desc, NULL);
159258
}
160259
else if (info == XLOG_HEAP2_LOCK_UPDATED)
161260
{
162261
xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
163262

164-
appendStringInfo(buf, "off %u: xmax %u: flags 0x%02X ",
263+
appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
165264
xlrec->offnum, xlrec->xmax, xlrec->flags);
166265
out_infobits(buf, xlrec->infobits_set);
167266
}
168267
else if (info == XLOG_HEAP2_NEW_CID)
169268
{
170269
xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec;
171270

172-
appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u",
271+
appendStringInfo(buf, "rel: %u/%u/%u, tid: %u/%u",
173272
xlrec->target_locator.spcOid,
174273
xlrec->target_locator.dbOid,
175274
xlrec->target_locator.relNumber,
176275
ItemPointerGetBlockNumber(&(xlrec->target_tid)),
177276
ItemPointerGetOffsetNumber(&(xlrec->target_tid)));
178-
appendStringInfo(buf, "; cmin: %u, cmax: %u, combo: %u",
277+
appendStringInfo(buf, ", cmin: %u, cmax: %u, combo: %u",
179278
xlrec->cmin, xlrec->cmax, xlrec->combocid);
180279
}
181280
}

src/backend/access/rmgrdesc/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ rmgr_desc_sources = files(
1616
'nbtdesc.c',
1717
'relmapdesc.c',
1818
'replorigindesc.c',
19+
'rmgrdesc_utils.c',
1920
'seqdesc.c',
2021
'smgrdesc.c',
2122
'spgdesc.c',

0 commit comments

Comments
 (0)