PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
brin_xlog.c
Go to the documentation of this file.
1/*
2 * brin_xlog.c
3 * XLog replay routines for BRIN indexes
4 *
5 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
7 *
8 * IDENTIFICATION
9 * src/backend/access/brin/brin_xlog.c
10 */
11#include "postgres.h"
12
13#include "access/brin_page.h"
14#include "access/brin_pageops.h"
15#include "access/brin_xlog.h"
16#include "access/bufmask.h"
17#include "access/xlogutils.h"
18
19
20/*
21 * xlog replay routines
22 */
23static void
25{
26 XLogRecPtr lsn = record->EndRecPtr;
28 Buffer buf;
29 Page page;
30
31 /* create the index' metapage */
32 buf = XLogInitBufferForRedo(record, 0);
34 page = (Page) BufferGetPage(buf);
35 brin_metapage_init(page, xlrec->pagesPerRange, xlrec->version);
36 PageSetLSN(page, lsn);
39}
40
41/*
42 * Common part of an insert or update. Inserts the new tuple and updates the
43 * revmap.
44 */
45static void
47 xl_brin_insert *xlrec)
48{
49 XLogRecPtr lsn = record->EndRecPtr;
50 Buffer buffer;
51 BlockNumber regpgno;
52 Page page;
54
55 /*
56 * If we inserted the first and only tuple on the page, re-initialize the
57 * page from scratch.
58 */
60 {
61 buffer = XLogInitBufferForRedo(record, 0);
62 page = BufferGetPage(buffer);
65 }
66 else
67 {
68 action = XLogReadBufferForRedo(record, 0, &buffer);
69 }
70
71 /* need this page's blkno to store in revmap */
72 regpgno = BufferGetBlockNumber(buffer);
73
74 /* insert the index item into the page */
76 {
77 OffsetNumber offnum;
78 BrinTuple *tuple;
79 Size tuplen;
80
81 tuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
82
83 Assert(tuple->bt_blkno == xlrec->heapBlk);
84
85 page = (Page) BufferGetPage(buffer);
86 offnum = xlrec->offnum;
87 if (PageGetMaxOffsetNumber(page) + 1 < offnum)
88 elog(PANIC, "brin_xlog_insert_update: invalid max offset number");
89
90 offnum = PageAddItem(page, (Item) tuple, tuplen, offnum, true, false);
91 if (offnum == InvalidOffsetNumber)
92 elog(PANIC, "brin_xlog_insert_update: failed to add tuple");
93
94 PageSetLSN(page, lsn);
95 MarkBufferDirty(buffer);
96 }
97 if (BufferIsValid(buffer))
98 UnlockReleaseBuffer(buffer);
99
100 /* update the revmap */
101 action = XLogReadBufferForRedo(record, 1, &buffer);
102 if (action == BLK_NEEDS_REDO)
103 {
104 ItemPointerData tid;
105
106 ItemPointerSet(&tid, regpgno, xlrec->offnum);
107 page = (Page) BufferGetPage(buffer);
108
109 brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk,
110 tid);
111 PageSetLSN(page, lsn);
112 MarkBufferDirty(buffer);
113 }
114 if (BufferIsValid(buffer))
115 UnlockReleaseBuffer(buffer);
116
117 /* XXX no FSM updates here ... */
118}
119
120/*
121 * replay a BRIN index insertion
122 */
123static void
125{
126 xl_brin_insert *xlrec = (xl_brin_insert *) XLogRecGetData(record);
127
128 brin_xlog_insert_update(record, xlrec);
129}
130
131/*
132 * replay a BRIN index update
133 */
134static void
136{
137 XLogRecPtr lsn = record->EndRecPtr;
138 xl_brin_update *xlrec = (xl_brin_update *) XLogRecGetData(record);
139 Buffer buffer;
141
142 /* First remove the old tuple */
143 action = XLogReadBufferForRedo(record, 2, &buffer);
144 if (action == BLK_NEEDS_REDO)
145 {
146 Page page;
147 OffsetNumber offnum;
148
149 page = (Page) BufferGetPage(buffer);
150
151 offnum = xlrec->oldOffnum;
152
153 PageIndexTupleDeleteNoCompact(page, offnum);
154
155 PageSetLSN(page, lsn);
156 MarkBufferDirty(buffer);
157 }
158
159 /* Then insert the new tuple and update revmap, like in an insertion. */
160 brin_xlog_insert_update(record, &xlrec->insert);
161
162 if (BufferIsValid(buffer))
163 UnlockReleaseBuffer(buffer);
164}
165
166/*
167 * Update a tuple on a single page.
168 */
169static void
171{
172 XLogRecPtr lsn = record->EndRecPtr;
174 Buffer buffer;
176
177 xlrec = (xl_brin_samepage_update *) XLogRecGetData(record);
178 action = XLogReadBufferForRedo(record, 0, &buffer);
179 if (action == BLK_NEEDS_REDO)
180 {
181 Size tuplen;
182 BrinTuple *brintuple;
183 Page page;
184 OffsetNumber offnum;
185
186 brintuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
187
188 page = (Page) BufferGetPage(buffer);
189
190 offnum = xlrec->offnum;
191
192 if (!PageIndexTupleOverwrite(page, offnum, (Item) brintuple, tuplen))
193 elog(PANIC, "brin_xlog_samepage_update: failed to replace tuple");
194
195 PageSetLSN(page, lsn);
196 MarkBufferDirty(buffer);
197 }
198 if (BufferIsValid(buffer))
199 UnlockReleaseBuffer(buffer);
200
201 /* XXX no FSM updates here ... */
202}
203
204/*
205 * Replay a revmap page extension
206 */
207static void
209{
210 XLogRecPtr lsn = record->EndRecPtr;
212 Buffer metabuf;
213 Buffer buf;
214 Page page;
215 BlockNumber targetBlk;
217
218 xlrec = (xl_brin_revmap_extend *) XLogRecGetData(record);
219
220 XLogRecGetBlockTag(record, 1, NULL, NULL, &targetBlk);
221 Assert(xlrec->targetBlk == targetBlk);
222
223 /* Update the metapage */
224 action = XLogReadBufferForRedo(record, 0, &metabuf);
225 if (action == BLK_NEEDS_REDO)
226 {
227 Page metapg;
228 BrinMetaPageData *metadata;
229
230 metapg = BufferGetPage(metabuf);
231 metadata = (BrinMetaPageData *) PageGetContents(metapg);
232
233 Assert(metadata->lastRevmapPage == xlrec->targetBlk - 1);
234 metadata->lastRevmapPage = xlrec->targetBlk;
235
236 PageSetLSN(metapg, lsn);
237
238 /*
239 * Set pd_lower just past the end of the metadata. This is essential,
240 * because without doing so, metadata will be lost if xlog.c
241 * compresses the page. (We must do this here because pre-v11
242 * versions of PG did not set the metapage's pd_lower correctly, so a
243 * pg_upgraded index might contain the wrong value.)
244 */
245 ((PageHeader) metapg)->pd_lower =
246 ((char *) metadata + sizeof(BrinMetaPageData)) - (char *) metapg;
247
248 MarkBufferDirty(metabuf);
249 }
250
251 /*
252 * Re-init the target block as a revmap page. There's never a full- page
253 * image here.
254 */
255
256 buf = XLogInitBufferForRedo(record, 1);
257 page = (Page) BufferGetPage(buf);
259
260 PageSetLSN(page, lsn);
262
264 if (BufferIsValid(metabuf))
265 UnlockReleaseBuffer(metabuf);
266}
267
268static void
270{
271 XLogRecPtr lsn = record->EndRecPtr;
272 xl_brin_desummarize *xlrec;
273 Buffer buffer;
275
276 xlrec = (xl_brin_desummarize *) XLogRecGetData(record);
277
278 /* Update the revmap */
279 action = XLogReadBufferForRedo(record, 0, &buffer);
280 if (action == BLK_NEEDS_REDO)
281 {
282 ItemPointerData iptr;
283
285 brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk, iptr);
286
287 PageSetLSN(BufferGetPage(buffer), lsn);
288 MarkBufferDirty(buffer);
289 }
290 if (BufferIsValid(buffer))
291 UnlockReleaseBuffer(buffer);
292
293 /* remove the leftover entry from the regular page */
294 action = XLogReadBufferForRedo(record, 1, &buffer);
295 if (action == BLK_NEEDS_REDO)
296 {
297 Page regPg = BufferGetPage(buffer);
298
300
301 PageSetLSN(regPg, lsn);
302 MarkBufferDirty(buffer);
303 }
304 if (BufferIsValid(buffer))
305 UnlockReleaseBuffer(buffer);
306}
307
308void
310{
311 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
312
313 switch (info & XLOG_BRIN_OPMASK)
314 {
316 brin_xlog_createidx(record);
317 break;
318 case XLOG_BRIN_INSERT:
319 brin_xlog_insert(record);
320 break;
321 case XLOG_BRIN_UPDATE:
322 brin_xlog_update(record);
323 break;
326 break;
329 break;
332 break;
333 default:
334 elog(PANIC, "brin_redo: unknown op code %u", info);
335 }
336}
337
338/*
339 * Mask a BRIN page before doing consistency checks.
340 */
341void
342brin_mask(char *pagedata, BlockNumber blkno)
343{
344 Page page = (Page) pagedata;
345 PageHeader pagehdr = (PageHeader) page;
346
348
350
351 /*
352 * Regular brin pages contain unused space which needs to be masked.
353 * Similarly for meta pages, but mask it only if pd_lower appears to have
354 * been set correctly.
355 */
356 if (BRIN_IS_REGULAR_PAGE(page) ||
357 (BRIN_IS_META_PAGE(page) && pagehdr->pd_lower > SizeOfPageHeaderData))
358 {
359 mask_unused_space(page);
360 }
361
362 /*
363 * BRIN_EVACUATE_PAGE is not WAL-logged, since it's of no use in recovery.
364 * Mask it. See brin_start_evacuating_page() for details.
365 */
366 BrinPageFlags(page) &= ~BRIN_EVACUATE_PAGE;
367}
uint32 BlockNumber
Definition: block.h:31
#define BRIN_IS_META_PAGE(page)
Definition: brin_page.h:55
#define BrinPageFlags(page)
Definition: brin_page.h:46
#define BRIN_PAGETYPE_REVMAP
Definition: brin_page.h:52
#define BRIN_PAGETYPE_REGULAR
Definition: brin_page.h:53
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:475
void brin_metapage_init(Page page, BlockNumber pagesPerRange, uint16 version)
Definition: brin_pageops.c:486
void brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange, BlockNumber heapBlk, ItemPointerData tid)
Definition: brin_revmap.c:155
static void brin_xlog_desummarize_page(XLogReaderState *record)
Definition: brin_xlog.c:269
void brin_redo(XLogReaderState *record)
Definition: brin_xlog.c:309
static void brin_xlog_update(XLogReaderState *record)
Definition: brin_xlog.c:135
static void brin_xlog_revmap_extend(XLogReaderState *record)
Definition: brin_xlog.c:208
static void brin_xlog_createidx(XLogReaderState *record)
Definition: brin_xlog.c:24
static void brin_xlog_insert(XLogReaderState *record)
Definition: brin_xlog.c:124
static void brin_xlog_insert_update(XLogReaderState *record, xl_brin_insert *xlrec)
Definition: brin_xlog.c:46
void brin_mask(char *pagedata, BlockNumber blkno)
Definition: brin_xlog.c:342
static void brin_xlog_samepage_update(XLogReaderState *record)
Definition: brin_xlog.c:170
#define XLOG_BRIN_REVMAP_EXTEND
Definition: brin_xlog.h:35
#define XLOG_BRIN_SAMEPAGE_UPDATE
Definition: brin_xlog.h:34
#define XLOG_BRIN_DESUMMARIZE
Definition: brin_xlog.h:36
#define XLOG_BRIN_CREATE_INDEX
Definition: brin_xlog.h:31
#define XLOG_BRIN_OPMASK
Definition: brin_xlog.h:38
#define XLOG_BRIN_INIT_PAGE
Definition: brin_xlog.h:43
#define XLOG_BRIN_UPDATE
Definition: brin_xlog.h:33
#define XLOG_BRIN_INSERT
Definition: brin_xlog.h:32
int Buffer
Definition: buf.h:23
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
void mask_unused_space(Page page)
Definition: bufmask.c:71
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3724
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4941
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2532
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:400
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:351
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1394
void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum)
Definition: bufpage.c:1284
PageHeaderData * PageHeader
Definition: bufpage.h:173
Pointer Page
Definition: bufpage.h:81
#define SizeOfPageHeaderData
Definition: bufpage.h:216
static char * PageGetContents(Page page)
Definition: bufpage.h:257
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
static OffsetNumber PageGetMaxOffsetNumber(Page page)
Definition: bufpage.h:372
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:471
uint8_t uint8
Definition: c.h:483
#define Assert(condition)
Definition: c.h:812
size_t Size
Definition: c.h:559
#define PANIC
Definition: elog.h:42
#define elog(elevel,...)
Definition: elog.h:225
Pointer Item
Definition: item.h:17
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition: itemptr.h:135
static void ItemPointerSetInvalid(ItemPointerData *pointer)
Definition: itemptr.h:184
#define InvalidOffsetNumber
Definition: off.h:26
uint16 OffsetNumber
Definition: off.h:24
static char * buf
Definition: pg_test_fsync.c:72
BlockNumber lastRevmapPage
Definition: brin_page.h:69
BlockNumber bt_blkno
Definition: brin_tuple.h:66
LocationIndex pd_lower
Definition: bufpage.h:165
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
BlockNumber pagesPerRange
Definition: brin_xlog.h:52
BlockNumber pagesPerRange
Definition: brin_xlog.h:135
BlockNumber heapBlk
Definition: brin_xlog.h:137
OffsetNumber regOffset
Definition: brin_xlog.h:139
OffsetNumber offnum
Definition: brin_xlog.h:71
BlockNumber pagesPerRange
Definition: brin_xlog.h:68
BlockNumber heapBlk
Definition: brin_xlog.h:65
BlockNumber targetBlk
Definition: brin_xlog.h:121
OffsetNumber offnum
Definition: brin_xlog.h:104
OffsetNumber oldOffnum
Definition: brin_xlog.h:90
xl_brin_insert insert
Definition: brin_xlog.h:92
uint64 XLogRecPtr
Definition: xlogdefs.h:21
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:2025
void XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1971
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:314
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:326
XLogRedoAction
Definition: xlogutils.h:73
@ BLK_NEEDS_REDO
Definition: xlogutils.h:74