]> granicus.if.org Git - postgresql/blob - src/backend/access/brin/brin_xlog.c
Revert no-op changes to BufferGetPage()
[postgresql] / src / backend / access / brin / brin_xlog.c
1 /*
2  * brin_xlog.c
3  *              XLog replay routines for BRIN indexes
4  *
5  * Portions Copyright (c) 1996-2016, 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/xlogutils.h"
17
18
19 /*
20  * xlog replay routines
21  */
22 static void
23 brin_xlog_createidx(XLogReaderState *record)
24 {
25         XLogRecPtr      lsn = record->EndRecPtr;
26         xl_brin_createidx *xlrec = (xl_brin_createidx *) XLogRecGetData(record);
27         Buffer          buf;
28         Page            page;
29
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);
36         MarkBufferDirty(buf);
37         UnlockReleaseBuffer(buf);
38 }
39
40 /*
41  * Common part of an insert or update. Inserts the new tuple and updates the
42  * revmap.
43  */
44 static void
45 brin_xlog_insert_update(XLogReaderState *record,
46                                                 xl_brin_insert *xlrec)
47 {
48         XLogRecPtr      lsn = record->EndRecPtr;
49         Buffer          buffer;
50         BlockNumber     regpgno;
51         Page            page;
52         XLogRedoAction action;
53
54         /*
55          * If we inserted the first and only tuple on the page, re-initialize the
56          * page from scratch.
57          */
58         if (XLogRecGetInfo(record) & XLOG_BRIN_INIT_PAGE)
59         {
60                 buffer = XLogInitBufferForRedo(record, 0);
61                 page = BufferGetPage(buffer);
62                 brin_page_init(page, BRIN_PAGETYPE_REGULAR);
63                 action = BLK_NEEDS_REDO;
64         }
65         else
66         {
67                 action = XLogReadBufferForRedo(record, 0, &buffer);
68         }
69
70         /* need this page's blkno to store in revmap */
71         regpgno = BufferGetBlockNumber(buffer);
72
73         /* insert the index item into the page */
74         if (action == BLK_NEEDS_REDO)
75         {
76                 OffsetNumber offnum;
77                 BrinTuple  *tuple;
78                 Size            tuplen;
79
80                 tuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
81
82                 Assert(tuple->bt_blkno == xlrec->heapBlk);
83
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");
88
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");
92
93                 PageSetLSN(page, lsn);
94                 MarkBufferDirty(buffer);
95         }
96         if (BufferIsValid(buffer))
97                 UnlockReleaseBuffer(buffer);
98
99         /* update the revmap */
100         action = XLogReadBufferForRedo(record, 1, &buffer);
101         if (action == BLK_NEEDS_REDO)
102         {
103                 ItemPointerData tid;
104
105                 ItemPointerSet(&tid, regpgno, xlrec->offnum);
106                 page = (Page) BufferGetPage(buffer);
107
108                 brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk,
109                                                                 tid);
110                 PageSetLSN(page, lsn);
111                 MarkBufferDirty(buffer);
112         }
113         if (BufferIsValid(buffer))
114                 UnlockReleaseBuffer(buffer);
115
116         /* XXX no FSM updates here ... */
117 }
118
119 /*
120  * replay a BRIN index insertion
121  */
122 static void
123 brin_xlog_insert(XLogReaderState *record)
124 {
125         xl_brin_insert *xlrec = (xl_brin_insert *) XLogRecGetData(record);
126
127         brin_xlog_insert_update(record, xlrec);
128 }
129
130 /*
131  * replay a BRIN index update
132  */
133 static void
134 brin_xlog_update(XLogReaderState *record)
135 {
136         XLogRecPtr      lsn = record->EndRecPtr;
137         xl_brin_update *xlrec = (xl_brin_update *) XLogRecGetData(record);
138         Buffer          buffer;
139         XLogRedoAction action;
140
141         /* First remove the old tuple */
142         action = XLogReadBufferForRedo(record, 2, &buffer);
143         if (action == BLK_NEEDS_REDO)
144         {
145                 Page            page;
146                 OffsetNumber offnum;
147
148                 page = (Page) BufferGetPage(buffer);
149
150                 offnum = xlrec->oldOffnum;
151                 if (PageGetMaxOffsetNumber(page) + 1 < offnum)
152                         elog(PANIC, "brin_xlog_update: invalid max offset number");
153
154                 PageIndexDeleteNoCompact(page, &offnum, 1);
155
156                 PageSetLSN(page, lsn);
157                 MarkBufferDirty(buffer);
158         }
159
160         /* Then insert the new tuple and update revmap, like in an insertion. */
161         brin_xlog_insert_update(record, &xlrec->insert);
162
163         if (BufferIsValid(buffer))
164                 UnlockReleaseBuffer(buffer);
165 }
166
167 /*
168  * Update a tuple on a single page.
169  */
170 static void
171 brin_xlog_samepage_update(XLogReaderState *record)
172 {
173         XLogRecPtr      lsn = record->EndRecPtr;
174         xl_brin_samepage_update *xlrec;
175         Buffer          buffer;
176         XLogRedoAction action;
177
178         xlrec = (xl_brin_samepage_update *) XLogRecGetData(record);
179         action = XLogReadBufferForRedo(record, 0, &buffer);
180         if (action == BLK_NEEDS_REDO)
181         {
182                 Size            tuplen;
183                 BrinTuple  *brintuple;
184                 Page            page;
185                 OffsetNumber offnum;
186
187                 brintuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
188
189                 page = (Page) BufferGetPage(buffer);
190
191                 offnum = xlrec->offnum;
192                 if (PageGetMaxOffsetNumber(page) + 1 < offnum)
193                         elog(PANIC, "brin_xlog_samepage_update: invalid max offset number");
194
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");
199
200                 PageSetLSN(page, lsn);
201                 MarkBufferDirty(buffer);
202         }
203         if (BufferIsValid(buffer))
204                 UnlockReleaseBuffer(buffer);
205
206         /* XXX no FSM updates here ... */
207 }
208
209 /*
210  * Replay a revmap page extension
211  */
212 static void
213 brin_xlog_revmap_extend(XLogReaderState *record)
214 {
215         XLogRecPtr      lsn = record->EndRecPtr;
216         xl_brin_revmap_extend *xlrec;
217         Buffer          metabuf;
218         Buffer          buf;
219         Page            page;
220         BlockNumber targetBlk;
221         XLogRedoAction action;
222
223         xlrec = (xl_brin_revmap_extend *) XLogRecGetData(record);
224
225         XLogRecGetBlockTag(record, 1, NULL, NULL, &targetBlk);
226         Assert(xlrec->targetBlk == targetBlk);
227
228         /* Update the metapage */
229         action = XLogReadBufferForRedo(record, 0, &metabuf);
230         if (action == BLK_NEEDS_REDO)
231         {
232                 Page            metapg;
233                 BrinMetaPageData *metadata;
234
235                 metapg = BufferGetPage(metabuf);
236                 metadata = (BrinMetaPageData *) PageGetContents(metapg);
237
238                 Assert(metadata->lastRevmapPage == xlrec->targetBlk - 1);
239                 metadata->lastRevmapPage = xlrec->targetBlk;
240
241                 PageSetLSN(metapg, lsn);
242                 MarkBufferDirty(metabuf);
243         }
244
245         /*
246          * Re-init the target block as a revmap page.  There's never a full- page
247          * image here.
248          */
249
250         buf = XLogInitBufferForRedo(record, 1);
251         page = (Page) BufferGetPage(buf);
252         brin_page_init(page, BRIN_PAGETYPE_REVMAP);
253
254         PageSetLSN(page, lsn);
255         MarkBufferDirty(buf);
256
257         UnlockReleaseBuffer(buf);
258         if (BufferIsValid(metabuf))
259                 UnlockReleaseBuffer(metabuf);
260 }
261
262 void
263 brin_redo(XLogReaderState *record)
264 {
265         uint8           info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
266
267         switch (info & XLOG_BRIN_OPMASK)
268         {
269                 case XLOG_BRIN_CREATE_INDEX:
270                         brin_xlog_createidx(record);
271                         break;
272                 case XLOG_BRIN_INSERT:
273                         brin_xlog_insert(record);
274                         break;
275                 case XLOG_BRIN_UPDATE:
276                         brin_xlog_update(record);
277                         break;
278                 case XLOG_BRIN_SAMEPAGE_UPDATE:
279                         brin_xlog_samepage_update(record);
280                         break;
281                 case XLOG_BRIN_REVMAP_EXTEND:
282                         brin_xlog_revmap_extend(record);
283                         break;
284                 default:
285                         elog(PANIC, "brin_redo: unknown op code %u", info);
286         }
287 }