PostgreSQL Source Code  git master
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-2017, 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  */
23 static void
25 {
26  XLogRecPtr lsn = record->EndRecPtr;
28  Buffer buf;
29  Page page;
30 
31  /* create the index' metapage */
32  buf = XLogInitBufferForRedo(record, 0);
33  Assert(BufferIsValid(buf));
34  page = (Page) BufferGetPage(buf);
35  brin_metapage_init(page, xlrec->pagesPerRange, xlrec->version);
36  PageSetLSN(page, lsn);
37  MarkBufferDirty(buf);
39 }
40 
41 /*
42  * Common part of an insert or update. Inserts the new tuple and updates the
43  * revmap.
44  */
45 static 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  */
59  if (XLogRecGetInfo(record) & XLOG_BRIN_INIT_PAGE)
60  {
61  buffer = XLogInitBufferForRedo(record, 0);
62  page = BufferGetPage(buffer);
64  action = BLK_NEEDS_REDO;
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 */
75  if (action == BLK_NEEDS_REDO)
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  */
123 static 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  */
134 static 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  */
169 static 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  */
207 static void
209 {
210  XLogRecPtr lsn = record->EndRecPtr;
211  xl_brin_revmap_extend *xlrec;
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);
261  MarkBufferDirty(buf);
262 
263  UnlockReleaseBuffer(buf);
264  if (BufferIsValid(metabuf))
265  UnlockReleaseBuffer(metabuf);
266 }
267 
268 static 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 
284  ItemPointerSetInvalid(&iptr);
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 
308 void
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;
328  brin_xlog_revmap_extend(record);
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  */
341 void
342 brin_mask(char *pagedata, BlockNumber blkno)
343 {
344  Page page = (Page) pagedata;
345  PageHeader pagehdr = (PageHeader) page;
346 
348 
349  mask_page_hint_bits(page);
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 }
BlockNumber heapBlk
Definition: brin_xlog.h:65
OffsetNumber regOffset
Definition: brin_xlog.h:139
static void brin_xlog_revmap_extend(XLogReaderState *record)
Definition: brin_xlog.c:208
static void brin_xlog_update(XLogReaderState *record)
Definition: brin_xlog.c:135
BlockNumber pagesPerRange
Definition: brin_xlog.h:135
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
static void brin_xlog_createidx(XLogReaderState *record)
Definition: brin_xlog.c:24
OffsetNumber offnum
Definition: brin_xlog.h:104
unsigned char uint8
Definition: c.h:304
#define XLOG_BRIN_CREATE_INDEX
Definition: brin_xlog.h:31
Pointer Item
Definition: item.h:17
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
uint32 BlockNumber
Definition: block.h:31
#define SizeOfPageHeaderData
Definition: bufpage.h:212
#define PANIC
Definition: elog.h:53
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
void mask_unused_space(Page page)
Definition: bufmask.c:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:120
uint16 OffsetNumber
Definition: off.h:24
#define XLOG_BRIN_UPDATE
Definition: brin_xlog.h:33
static void brin_xlog_insert(XLogReaderState *record)
Definition: brin_xlog.c:124
#define XLogRecGetData(decoder)
Definition: xlogreader.h:226
void brin_metapage_init(Page page, BlockNumber pagesPerRange, uint16 version)
Definition: brin_pageops.c:482
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define XLOG_BRIN_DESUMMARIZE
Definition: brin_xlog.h:36
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
static void brin_xlog_desummarize_page(XLogReaderState *record)
Definition: brin_xlog.c:269
#define BRIN_PAGETYPE_REGULAR
Definition: brin_page.h:53
void brin_mask(char *pagedata, BlockNumber blkno)
Definition: brin_xlog.c:342
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1062
BlockNumber pagesPerRange
Definition: brin_xlog.h:68
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
BlockNumber targetBlk
Definition: brin_xlog.h:121
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:222
#define XLOG_BRIN_REVMAP_EXTEND
Definition: brin_xlog.h:35
BlockNumber lastRevmapPage
Definition: brin_page.h:69
#define XLOG_BRIN_INIT_PAGE
Definition: brin_xlog.h:43
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1330
#define BRIN_IS_META_PAGE(page)
Definition: brin_page.h:55
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1354
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
#define PageGetContents(page)
Definition: bufpage.h:242
#define XLOG_BRIN_INSERT
Definition: brin_xlog.h:32
#define InvalidOffsetNumber
Definition: off.h:26
xl_brin_insert insert
Definition: brin_xlog.h:92
BlockNumber bt_blkno
Definition: brin_tuple.h:57
void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum)
Definition: bufpage.c:954
static void brin_xlog_samepage_update(XLogReaderState *record)
Definition: brin_xlog.c:170
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
PageHeaderData * PageHeader
Definition: bufpage.h:162
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:680
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
XLogRedoAction
Definition: xlogutils.h:27
#define BRIN_PAGETYPE_REVMAP
Definition: brin_page.h:52
size_t Size
Definition: c.h:414
#define XLOG_BRIN_SAMEPAGE_UPDATE
Definition: brin_xlog.h:34
OffsetNumber offnum
Definition: brin_xlog.h:71
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
BlockNumber heapBlk
Definition: brin_xlog.h:137
static void brin_xlog_insert_update(XLogReaderState *record, xl_brin_insert *xlrec)
Definition: brin_xlog.c:46
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
void brin_redo(XLogReaderState *record)
Definition: brin_xlog.c:309
#define XLOG_BRIN_OPMASK
Definition: brin_xlog.h:38
BlockNumber pagesPerRange
Definition: brin_xlog.h:52
#define elog
Definition: elog.h:219
void brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange, BlockNumber heapBlk, ItemPointerData tid)
Definition: brin_revmap.c:158
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
OffsetNumber oldOffnum
Definition: brin_xlog.h:90
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:105
LocationIndex pd_lower
Definition: bufpage.h:154
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:471