PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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;
53  XLogRedoAction action;
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;
140  XLogRedoAction action;
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;
175  XLogRedoAction action;
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;
216  XLogRedoAction action;
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  MarkBufferDirty(metabuf);
238  }
239 
240  /*
241  * Re-init the target block as a revmap page. There's never a full- page
242  * image here.
243  */
244 
245  buf = XLogInitBufferForRedo(record, 1);
246  page = (Page) BufferGetPage(buf);
248 
249  PageSetLSN(page, lsn);
250  MarkBufferDirty(buf);
251 
252  UnlockReleaseBuffer(buf);
253  if (BufferIsValid(metabuf))
254  UnlockReleaseBuffer(metabuf);
255 }
256 
257 static void
259 {
260  XLogRecPtr lsn = record->EndRecPtr;
261  xl_brin_desummarize *xlrec;
262  Buffer buffer;
263  XLogRedoAction action;
264 
265  xlrec = (xl_brin_desummarize *) XLogRecGetData(record);
266 
267  /* Update the revmap */
268  action = XLogReadBufferForRedo(record, 0, &buffer);
269  if (action == BLK_NEEDS_REDO)
270  {
271  ItemPointerData iptr;
272 
273  ItemPointerSetInvalid(&iptr);
274  brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk, iptr);
275 
276  PageSetLSN(BufferGetPage(buffer), lsn);
277  MarkBufferDirty(buffer);
278  }
279  if (BufferIsValid(buffer))
280  UnlockReleaseBuffer(buffer);
281 
282  /* remove the leftover entry from the regular page */
283  action = XLogReadBufferForRedo(record, 1, &buffer);
284  if (action == BLK_NEEDS_REDO)
285  {
286  Page regPg = BufferGetPage(buffer);
287 
289 
290  PageSetLSN(regPg, lsn);
291  MarkBufferDirty(buffer);
292  }
293  if (BufferIsValid(buffer))
294  UnlockReleaseBuffer(buffer);
295 }
296 
297 void
299 {
300  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
301 
302  switch (info & XLOG_BRIN_OPMASK)
303  {
305  brin_xlog_createidx(record);
306  break;
307  case XLOG_BRIN_INSERT:
308  brin_xlog_insert(record);
309  break;
310  case XLOG_BRIN_UPDATE:
311  brin_xlog_update(record);
312  break;
315  break;
317  brin_xlog_revmap_extend(record);
318  break;
321  break;
322  default:
323  elog(PANIC, "brin_redo: unknown op code %u", info);
324  }
325 }
326 
327 /*
328  * Mask a BRIN page before doing consistency checks.
329  */
330 void
331 brin_mask(char *pagedata, BlockNumber blkno)
332 {
333  Page page = (Page) pagedata;
334 
335  mask_page_lsn(page);
336 
337  mask_page_hint_bits(page);
338 
339  if (BRIN_IS_REGULAR_PAGE(page))
340  {
341  /* Regular brin pages contain unused space which needs to be masked. */
342  mask_unused_space(page);
343  }
344 }
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:266
#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:44
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:413
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
uint32 BlockNumber
Definition: block.h:31
#define PANIC
Definition: elog.h:53
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:354
void mask_unused_space(Page page)
Definition: bufmask.c:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
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:220
void brin_metapage_init(Page page, BlockNumber pagesPerRange, uint16 version)
Definition: brin_pageops.c:480
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
void mask_page_lsn(Page page)
Definition: bufmask.c:30
#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:258
#define BRIN_PAGETYPE_REGULAR
Definition: brin_page.h:53
void brin_mask(char *pagedata, BlockNumber blkno)
Definition: brin_xlog.c:331
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1066
BlockNumber pagesPerRange
Definition: brin_xlog.h:68
static char * buf
Definition: pg_test_fsync.c:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
BlockNumber targetBlk
Definition: brin_xlog.h:121
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:216
#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:1307
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1331
#define PageGetContents(page)
Definition: bufpage.h:243
#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:958
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
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:211
XLogRedoAction
Definition: xlogutils.h:27
#define BRIN_PAGETYPE_REVMAP
Definition: brin_page.h:52
size_t Size
Definition: c.h:356
#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:149
void brin_redo(XLogReaderState *record)
Definition: brin_xlog.c:298
#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:365
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:104
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:469