3 * XLog replay routines for BRIN indexes
5 * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
9 * src/backend/access/brin/brin_xlog.c
13 #include "access/brin_page.h"
14 #include "access/brin_pageops.h"
15 #include "access/brin_xlog.h"
16 #include "access/xlogutils.h"
20 * xlog replay routines
23 brin_xlog_createidx(XLogReaderState *record)
25 XLogRecPtr lsn = record->EndRecPtr;
26 xl_brin_createidx *xlrec = (xl_brin_createidx *) XLogRecGetData(record);
30 /* create the index' metapage */
31 buf = XLogInitBufferForRedo(record, 0);
32 Assert(BufferIsValid(buf));
33 page = (Page) BufferGetPage(buf);
34 brin_metapage_init(page, xlrec->pagesPerRange, xlrec->version);
35 PageSetLSN(page, lsn);
37 UnlockReleaseBuffer(buf);
41 * Common part of an insert or update. Inserts the new tuple and updates the
45 brin_xlog_insert_update(XLogReaderState *record,
46 xl_brin_insert *xlrec)
48 XLogRecPtr lsn = record->EndRecPtr;
52 XLogRedoAction action;
55 * If we inserted the first and only tuple on the page, re-initialize the
58 if (XLogRecGetInfo(record) & XLOG_BRIN_INIT_PAGE)
60 buffer = XLogInitBufferForRedo(record, 0);
61 page = BufferGetPage(buffer);
62 brin_page_init(page, BRIN_PAGETYPE_REGULAR);
63 action = BLK_NEEDS_REDO;
67 action = XLogReadBufferForRedo(record, 0, &buffer);
70 /* need this page's blkno to store in revmap */
71 regpgno = BufferGetBlockNumber(buffer);
73 /* insert the index item into the page */
74 if (action == BLK_NEEDS_REDO)
80 tuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
82 Assert(tuple->bt_blkno == xlrec->heapBlk);
84 page = (Page) BufferGetPage(buffer);
85 offnum = xlrec->offnum;
86 if (PageGetMaxOffsetNumber(page) + 1 < offnum)
87 elog(PANIC, "brin_xlog_insert_update: invalid max offset number");
89 offnum = PageAddItem(page, (Item) tuple, tuplen, offnum, true, false);
90 if (offnum == InvalidOffsetNumber)
91 elog(PANIC, "brin_xlog_insert_update: failed to add tuple");
93 PageSetLSN(page, lsn);
94 MarkBufferDirty(buffer);
96 if (BufferIsValid(buffer))
97 UnlockReleaseBuffer(buffer);
99 /* update the revmap */
100 action = XLogReadBufferForRedo(record, 1, &buffer);
101 if (action == BLK_NEEDS_REDO)
105 ItemPointerSet(&tid, regpgno, xlrec->offnum);
106 page = (Page) BufferGetPage(buffer);
108 brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk,
110 PageSetLSN(page, lsn);
111 MarkBufferDirty(buffer);
113 if (BufferIsValid(buffer))
114 UnlockReleaseBuffer(buffer);
116 /* XXX no FSM updates here ... */
120 * replay a BRIN index insertion
123 brin_xlog_insert(XLogReaderState *record)
125 xl_brin_insert *xlrec = (xl_brin_insert *) XLogRecGetData(record);
127 brin_xlog_insert_update(record, xlrec);
131 * replay a BRIN index update
134 brin_xlog_update(XLogReaderState *record)
136 XLogRecPtr lsn = record->EndRecPtr;
137 xl_brin_update *xlrec = (xl_brin_update *) XLogRecGetData(record);
139 XLogRedoAction action;
141 /* First remove the old tuple */
142 action = XLogReadBufferForRedo(record, 2, &buffer);
143 if (action == BLK_NEEDS_REDO)
148 page = (Page) BufferGetPage(buffer);
150 offnum = xlrec->oldOffnum;
151 if (PageGetMaxOffsetNumber(page) + 1 < offnum)
152 elog(PANIC, "brin_xlog_update: invalid max offset number");
154 PageIndexDeleteNoCompact(page, &offnum, 1);
156 PageSetLSN(page, lsn);
157 MarkBufferDirty(buffer);
160 /* Then insert the new tuple and update revmap, like in an insertion. */
161 brin_xlog_insert_update(record, &xlrec->insert);
163 if (BufferIsValid(buffer))
164 UnlockReleaseBuffer(buffer);
168 * Update a tuple on a single page.
171 brin_xlog_samepage_update(XLogReaderState *record)
173 XLogRecPtr lsn = record->EndRecPtr;
174 xl_brin_samepage_update *xlrec;
176 XLogRedoAction action;
178 xlrec = (xl_brin_samepage_update *) XLogRecGetData(record);
179 action = XLogReadBufferForRedo(record, 0, &buffer);
180 if (action == BLK_NEEDS_REDO)
183 BrinTuple *brintuple;
187 brintuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
189 page = (Page) BufferGetPage(buffer);
191 offnum = xlrec->offnum;
192 if (PageGetMaxOffsetNumber(page) + 1 < offnum)
193 elog(PANIC, "brin_xlog_samepage_update: invalid max offset number");
195 PageIndexDeleteNoCompact(page, &offnum, 1);
196 offnum = PageAddItem(page, (Item) brintuple, tuplen, offnum, true, false);
197 if (offnum == InvalidOffsetNumber)
198 elog(PANIC, "brin_xlog_samepage_update: failed to add tuple");
200 PageSetLSN(page, lsn);
201 MarkBufferDirty(buffer);
203 if (BufferIsValid(buffer))
204 UnlockReleaseBuffer(buffer);
206 /* XXX no FSM updates here ... */
210 * Replay a revmap page extension
213 brin_xlog_revmap_extend(XLogReaderState *record)
215 XLogRecPtr lsn = record->EndRecPtr;
216 xl_brin_revmap_extend *xlrec;
220 BlockNumber targetBlk;
221 XLogRedoAction action;
223 xlrec = (xl_brin_revmap_extend *) XLogRecGetData(record);
225 XLogRecGetBlockTag(record, 1, NULL, NULL, &targetBlk);
226 Assert(xlrec->targetBlk == targetBlk);
228 /* Update the metapage */
229 action = XLogReadBufferForRedo(record, 0, &metabuf);
230 if (action == BLK_NEEDS_REDO)
233 BrinMetaPageData *metadata;
235 metapg = BufferGetPage(metabuf);
236 metadata = (BrinMetaPageData *) PageGetContents(metapg);
238 Assert(metadata->lastRevmapPage == xlrec->targetBlk - 1);
239 metadata->lastRevmapPage = xlrec->targetBlk;
241 PageSetLSN(metapg, lsn);
242 MarkBufferDirty(metabuf);
246 * Re-init the target block as a revmap page. There's never a full- page
250 buf = XLogInitBufferForRedo(record, 1);
251 page = (Page) BufferGetPage(buf);
252 brin_page_init(page, BRIN_PAGETYPE_REVMAP);
254 PageSetLSN(page, lsn);
255 MarkBufferDirty(buf);
257 UnlockReleaseBuffer(buf);
258 if (BufferIsValid(metabuf))
259 UnlockReleaseBuffer(metabuf);
263 brin_redo(XLogReaderState *record)
265 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
267 switch (info & XLOG_BRIN_OPMASK)
269 case XLOG_BRIN_CREATE_INDEX:
270 brin_xlog_createidx(record);
272 case XLOG_BRIN_INSERT:
273 brin_xlog_insert(record);
275 case XLOG_BRIN_UPDATE:
276 brin_xlog_update(record);
278 case XLOG_BRIN_SAMEPAGE_UPDATE:
279 brin_xlog_samepage_update(record);
281 case XLOG_BRIN_REVMAP_EXTEND:
282 brin_xlog_revmap_extend(record);
285 elog(PANIC, "brin_redo: unknown op code %u", info);