PostgreSQL Source Code  git master
brin_pageops.c File Reference
#include "postgres.h"
#include "access/brin_page.h"
#include "access/brin_pageops.h"
#include "access/brin_revmap.h"
#include "access/brin_xlog.h"
#include "access/xloginsert.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
#include "storage/freespace.h"
#include "storage/lmgr.h"
#include "storage/smgr.h"
#include "utils/rel.h"
Include dependency graph for brin_pageops.c:

Go to the source code of this file.

Macros

#define BrinMaxItemSize
 

Functions

static Buffer brin_getinsertbuffer (Relation irel, Buffer oldbuf, Size itemsz, bool *extended)
 
static Size br_page_get_freespace (Page page)
 
static void brin_initialize_empty_new_buffer (Relation idxrel, Buffer buffer)
 
bool brin_doupdate (Relation idxrel, BlockNumber pagesPerRange, BrinRevmap *revmap, BlockNumber heapBlk, Buffer oldbuf, OffsetNumber oldoff, const BrinTuple *origtup, Size origsz, const BrinTuple *newtup, Size newsz, bool samepage)
 
bool brin_can_do_samepage_update (Buffer buffer, Size origsz, Size newsz)
 
OffsetNumber brin_doinsert (Relation idxrel, BlockNumber pagesPerRange, BrinRevmap *revmap, Buffer *buffer, BlockNumber heapBlk, BrinTuple *tup, Size itemsz)
 
void brin_page_init (Page page, uint16 type)
 
void brin_metapage_init (Page page, BlockNumber pagesPerRange, uint16 version)
 
bool brin_start_evacuating_page (Relation idxRel, Buffer buf)
 
void brin_evacuate_page (Relation idxRel, BlockNumber pagesPerRange, BrinRevmap *revmap, Buffer buf)
 
void brin_page_cleanup (Relation idxrel, Buffer buf)
 

Macro Definition Documentation

◆ BrinMaxItemSize

#define BrinMaxItemSize
Value:
MAXALIGN_DOWN(BLCKSZ - \
sizeof(ItemIdData)) + \
#define SizeOfPageHeaderData
Definition: bufpage.h:216
#define MAXALIGN(LEN)
Definition: c.h:692
#define MAXALIGN_DOWN(LEN)
Definition: c.h:704

Definition at line 29 of file brin_pageops.c.

Referenced by brin_doinsert(), brin_doupdate(), and brin_getinsertbuffer().

Function Documentation

◆ br_page_get_freespace()

static Size br_page_get_freespace ( Page  page)
static

Definition at line 908 of file brin_pageops.c.

References BRIN_EVACUATE_PAGE, BRIN_IS_REGULAR_PAGE, BrinPageFlags, and PageGetFreeSpace().

Referenced by brin_doinsert(), brin_doupdate(), brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), and brin_page_cleanup().

909 {
910  if (!BRIN_IS_REGULAR_PAGE(page) ||
911  (BrinPageFlags(page) & BRIN_EVACUATE_PAGE) != 0)
912  return 0;
913  else
914  return PageGetFreeSpace(page);
915 }
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
Size PageGetFreeSpace(Page page)
Definition: bufpage.c:581
#define BRIN_EVACUATE_PAGE
Definition: brin_page.h:60
#define BrinPageFlags(page)
Definition: brin_page.h:46

◆ brin_can_do_samepage_update()

bool brin_can_do_samepage_update ( Buffer  buffer,
Size  origsz,
Size  newsz 
)

Definition at line 324 of file brin_pageops.c.

References BufferGetPage, and PageGetExactFreeSpace().

Referenced by brin_doupdate(), brininsert(), and summarize_range().

325 {
326  return
327  ((newsz <= origsz) ||
328  PageGetExactFreeSpace(BufferGetPage(buffer)) >= (newsz - origsz));
329 }
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
Size PageGetExactFreeSpace(Page page)
Definition: bufpage.c:632

◆ brin_doinsert()

OffsetNumber brin_doinsert ( Relation  idxrel,
BlockNumber  pagesPerRange,
BrinRevmap revmap,
Buffer buffer,
BlockNumber  heapBlk,
BrinTuple tup,
Size  itemsz 
)

Definition at line 343 of file brin_pageops.c.

References Assert, br_page_get_freespace(), BRIN_elog, brin_getinsertbuffer(), brin_page_init(), BRIN_PAGETYPE_REGULAR, brinLockRevmapPageForUpdate(), BrinMaxItemSize, brinRevmapExtend(), brinSetHeapBlockItemptr(), BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferIsValid, DEBUG2, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, FreeSpaceMapVacuumRange(), xl_brin_insert::heapBlk, InvalidBuffer, InvalidOffsetNumber, ItemPointerSet, LockBuffer(), MarkBufferDirty(), MAXALIGN, xl_brin_insert::offnum, PageAddItem, PageSetLSN, xl_brin_insert::pagesPerRange, RecordPageWithFreeSpace(), REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetRelationName, RelationNeedsWAL, SizeOfBrinInsert, START_CRIT_SECTION, UnlockReleaseBuffer(), XLOG_BRIN_INIT_PAGE, XLOG_BRIN_INSERT, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by form_and_insert_tuple(), and summarize_range().

346 {
347  Page page;
348  BlockNumber blk;
349  OffsetNumber off;
350  Size freespace = 0;
351  Buffer revmapbuf;
352  ItemPointerData tid;
353  bool extended;
354 
355  Assert(itemsz == MAXALIGN(itemsz));
356 
357  /* If the item is oversized, don't even bother. */
358  if (itemsz > BrinMaxItemSize)
359  {
360  ereport(ERROR,
361  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
362  errmsg("index row size %zu exceeds maximum %zu for index \"%s\"",
363  itemsz, BrinMaxItemSize, RelationGetRelationName(idxrel))));
364  return InvalidOffsetNumber; /* keep compiler quiet */
365  }
366 
367  /* Make sure the revmap is long enough to contain the entry we need */
368  brinRevmapExtend(revmap, heapBlk);
369 
370  /*
371  * Acquire lock on buffer supplied by caller, if any. If it doesn't have
372  * enough space, unpin it to obtain a new one below.
373  */
374  if (BufferIsValid(*buffer))
375  {
376  /*
377  * It's possible that another backend (or ourselves!) extended the
378  * revmap over the page we held a pin on, so we cannot assume that
379  * it's still a regular page.
380  */
382  if (br_page_get_freespace(BufferGetPage(*buffer)) < itemsz)
383  {
384  UnlockReleaseBuffer(*buffer);
385  *buffer = InvalidBuffer;
386  }
387  }
388 
389  /*
390  * If we still don't have a usable buffer, have brin_getinsertbuffer
391  * obtain one for us.
392  */
393  if (!BufferIsValid(*buffer))
394  {
395  do
396  *buffer = brin_getinsertbuffer(idxrel, InvalidBuffer, itemsz, &extended);
397  while (!BufferIsValid(*buffer));
398  }
399  else
400  extended = false;
401 
402  /* Now obtain lock on revmap buffer */
403  revmapbuf = brinLockRevmapPageForUpdate(revmap, heapBlk);
404 
405  page = BufferGetPage(*buffer);
406  blk = BufferGetBlockNumber(*buffer);
407 
408  /* Execute the actual insertion */
410  if (extended)
412  off = PageAddItem(page, (Item) tup, itemsz, InvalidOffsetNumber,
413  false, false);
414  if (off == InvalidOffsetNumber)
415  elog(ERROR, "failed to add BRIN tuple to new page");
416  MarkBufferDirty(*buffer);
417 
418  /* needed to update FSM below */
419  if (extended)
420  freespace = br_page_get_freespace(page);
421 
422  ItemPointerSet(&tid, blk, off);
423  brinSetHeapBlockItemptr(revmapbuf, pagesPerRange, heapBlk, tid);
424  MarkBufferDirty(revmapbuf);
425 
426  /* XLOG stuff */
427  if (RelationNeedsWAL(idxrel))
428  {
429  xl_brin_insert xlrec;
430  XLogRecPtr recptr;
431  uint8 info;
432 
433  info = XLOG_BRIN_INSERT | (extended ? XLOG_BRIN_INIT_PAGE : 0);
434  xlrec.heapBlk = heapBlk;
435  xlrec.pagesPerRange = pagesPerRange;
436  xlrec.offnum = off;
437 
438  XLogBeginInsert();
439  XLogRegisterData((char *) &xlrec, SizeOfBrinInsert);
440 
441  XLogRegisterBuffer(0, *buffer, REGBUF_STANDARD | (extended ? REGBUF_WILL_INIT : 0));
442  XLogRegisterBufData(0, (char *) tup, itemsz);
443 
444  XLogRegisterBuffer(1, revmapbuf, 0);
445 
446  recptr = XLogInsert(RM_BRIN_ID, info);
447 
448  PageSetLSN(page, recptr);
449  PageSetLSN(BufferGetPage(revmapbuf), recptr);
450  }
451 
453 
454  /* Tuple is firmly on buffer; we can release our locks */
455  LockBuffer(*buffer, BUFFER_LOCK_UNLOCK);
456  LockBuffer(revmapbuf, BUFFER_LOCK_UNLOCK);
457 
458  BRIN_elog((DEBUG2, "inserted tuple (%u,%u) for range starting at %u",
459  blk, off, heapBlk));
460 
461  if (extended)
462  {
463  RecordPageWithFreeSpace(idxrel, blk, freespace);
464  FreeSpaceMapVacuumRange(idxrel, blk, blk + 1);
465  }
466 
467  return off;
468 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
BlockNumber heapBlk
Definition: brin_xlog.h:65
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
#define BRIN_elog(args)
Definition: brin_internal.h:81
void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, Size spaceAvail)
Definition: freespace.c:181
#define SizeOfBrinInsert
Definition: brin_xlog.h:74
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
unsigned char uint8
Definition: c.h:357
Pointer Item
Definition: item.h:17
#define InvalidBuffer
Definition: buf.h:25
Buffer brinLockRevmapPageForUpdate(BrinRevmap *revmap, BlockNumber heapBlk)
Definition: brin_revmap.c:137
#define REGBUF_WILL_INIT
Definition: xloginsert.h:33
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
int errcode(int sqlerrcode)
Definition: elog.c:608
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
uint16 OffsetNumber
Definition: off.h:24
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3388
#define ERROR
Definition: elog.h:43
#define BRIN_PAGETYPE_REGULAR
Definition: brin_page.h:53
#define DEBUG2
Definition: elog.h:24
void brinRevmapExtend(BrinRevmap *revmap, BlockNumber heapBlk)
Definition: brin_revmap.c:115
BlockNumber pagesPerRange
Definition: brin_xlog.h:68
#define REGBUF_STANDARD
Definition: xloginsert.h:35
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:908
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define ereport(elevel, rest)
Definition: elog.h:141
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
#define XLOG_BRIN_INIT_PAGE
Definition: brin_xlog.h:43
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
#define XLOG_BRIN_INSERT
Definition: brin_xlog.h:32
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
#define InvalidOffsetNumber
Definition: off.h:26
#define BrinMaxItemSize
Definition: brin_pageops.c:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
OffsetNumber offnum
Definition: brin_xlog.h:71
#define MAXALIGN(LEN)
Definition: c.h:692
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define RelationNeedsWAL(relation)
Definition: rel.h:524
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
static Buffer brin_getinsertbuffer(Relation irel, Buffer oldbuf, Size itemsz, bool *extended)
Definition: brin_pageops.c:686
void brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange, BlockNumber heapBlk, ItemPointerData tid)
Definition: brin_revmap.c:158
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:352
Pointer Page
Definition: bufpage.h:78
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:476

◆ brin_doupdate()

bool brin_doupdate ( Relation  idxrel,
BlockNumber  pagesPerRange,
BrinRevmap revmap,
BlockNumber  heapBlk,
Buffer  oldbuf,
OffsetNumber  oldoff,
const BrinTuple origtup,
Size  origsz,
const BrinTuple newtup,
Size  newsz,
bool  samepage 
)

Definition at line 54 of file brin_pageops.c.

References Assert, br_page_get_freespace(), brin_can_do_samepage_update(), BRIN_EVACUATE_PAGE, brin_getinsertbuffer(), brin_initialize_empty_new_buffer(), BRIN_IS_REGULAR_PAGE, brin_page_init(), BRIN_PAGETYPE_REGULAR, brin_tuples_equal(), brinLockRevmapPageForUpdate(), BrinMaxItemSize, BrinPageFlags, brinRevmapExtend(), brinSetHeapBlockItemptr(), BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferIsValid, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, FreeSpaceMapVacuumRange(), xl_brin_insert::heapBlk, xl_brin_update::insert, InvalidBlockNumber, InvalidBuffer, InvalidOffsetNumber, ItemIdGetLength, ItemIdIsNormal, ItemPointerSet, LockBuffer(), MarkBufferDirty(), MAXALIGN, xl_brin_insert::offnum, xl_brin_samepage_update::offnum, xl_brin_update::oldOffnum, PageAddItem, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageIndexTupleDeleteNoCompact(), PageIndexTupleOverwrite(), PageSetLSN, xl_brin_insert::pagesPerRange, RecordPageWithFreeSpace(), REGBUF_STANDARD, REGBUF_WILL_INIT, RelationGetRelationName, RelationNeedsWAL, SizeOfBrinSamepageUpdate, SizeOfBrinUpdate, START_CRIT_SECTION, unconstify, UnlockReleaseBuffer(), XLOG_BRIN_INIT_PAGE, XLOG_BRIN_SAMEPAGE_UPDATE, XLOG_BRIN_UPDATE, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by brin_evacuate_page(), brininsert(), and summarize_range().

60 {
61  Page oldpage;
62  ItemId oldlp;
63  BrinTuple *oldtup;
64  Size oldsz;
65  Buffer newbuf;
67  bool extended;
68 
69  Assert(newsz == MAXALIGN(newsz));
70 
71  /* If the item is oversized, don't bother. */
72  if (newsz > BrinMaxItemSize)
73  {
74  ereport(ERROR,
75  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
76  errmsg("index row size %zu exceeds maximum %zu for index \"%s\"",
77  newsz, BrinMaxItemSize, RelationGetRelationName(idxrel))));
78  return false; /* keep compiler quiet */
79  }
80 
81  /* make sure the revmap is long enough to contain the entry we need */
82  brinRevmapExtend(revmap, heapBlk);
83 
84  if (!samepage)
85  {
86  /* need a page on which to put the item */
87  newbuf = brin_getinsertbuffer(idxrel, oldbuf, newsz, &extended);
88  if (!BufferIsValid(newbuf))
89  {
90  Assert(!extended);
91  return false;
92  }
93 
94  /*
95  * Note: it's possible (though unlikely) that the returned newbuf is
96  * the same as oldbuf, if brin_getinsertbuffer determined that the old
97  * buffer does in fact have enough space.
98  */
99  if (newbuf == oldbuf)
100  {
101  Assert(!extended);
102  newbuf = InvalidBuffer;
103  }
104  else
105  newblk = BufferGetBlockNumber(newbuf);
106  }
107  else
108  {
110  newbuf = InvalidBuffer;
111  extended = false;
112  }
113  oldpage = BufferGetPage(oldbuf);
114  oldlp = PageGetItemId(oldpage, oldoff);
115 
116  /*
117  * Check that the old tuple wasn't updated concurrently: it might have
118  * moved someplace else entirely, and for that matter the whole page
119  * might've become a revmap page. Note that in the first two cases
120  * checked here, the "oldlp" we just calculated is garbage; but
121  * PageGetItemId() is simple enough that it was safe to do that
122  * calculation anyway.
123  */
124  if (!BRIN_IS_REGULAR_PAGE(oldpage) ||
125  oldoff > PageGetMaxOffsetNumber(oldpage) ||
126  !ItemIdIsNormal(oldlp))
127  {
129 
130  /*
131  * If this happens, and the new buffer was obtained by extending the
132  * relation, then we need to ensure we don't leave it uninitialized or
133  * forget about it.
134  */
135  if (BufferIsValid(newbuf))
136  {
137  if (extended)
138  brin_initialize_empty_new_buffer(idxrel, newbuf);
139  UnlockReleaseBuffer(newbuf);
140  if (extended)
141  FreeSpaceMapVacuumRange(idxrel, newblk, newblk + 1);
142  }
143  return false;
144  }
145 
146  oldsz = ItemIdGetLength(oldlp);
147  oldtup = (BrinTuple *) PageGetItem(oldpage, oldlp);
148 
149  /*
150  * ... or it might have been updated in place to different contents.
151  */
152  if (!brin_tuples_equal(oldtup, oldsz, origtup, origsz))
153  {
155  if (BufferIsValid(newbuf))
156  {
157  /* As above, initialize and record new page if we got one */
158  if (extended)
159  brin_initialize_empty_new_buffer(idxrel, newbuf);
160  UnlockReleaseBuffer(newbuf);
161  if (extended)
162  FreeSpaceMapVacuumRange(idxrel, newblk, newblk + 1);
163  }
164  return false;
165  }
166 
167  /*
168  * Great, the old tuple is intact. We can proceed with the update.
169  *
170  * If there's enough room in the old page for the new tuple, replace it.
171  *
172  * Note that there might now be enough space on the page even though the
173  * caller told us there isn't, if a concurrent update moved another tuple
174  * elsewhere or replaced a tuple with a smaller one.
175  */
176  if (((BrinPageFlags(oldpage) & BRIN_EVACUATE_PAGE) == 0) &&
177  brin_can_do_samepage_update(oldbuf, origsz, newsz))
178  {
180  if (!PageIndexTupleOverwrite(oldpage, oldoff, (Item) unconstify(BrinTuple *, newtup), newsz))
181  elog(ERROR, "failed to replace BRIN tuple");
182  MarkBufferDirty(oldbuf);
183 
184  /* XLOG stuff */
185  if (RelationNeedsWAL(idxrel))
186  {
188  XLogRecPtr recptr;
190 
191  xlrec.offnum = oldoff;
192 
193  XLogBeginInsert();
194  XLogRegisterData((char *) &xlrec, SizeOfBrinSamepageUpdate);
195 
197  XLogRegisterBufData(0, (char *) unconstify(BrinTuple *, newtup), newsz);
198 
199  recptr = XLogInsert(RM_BRIN_ID, info);
200 
201  PageSetLSN(oldpage, recptr);
202  }
203 
205 
207 
208  if (BufferIsValid(newbuf))
209  {
210  /* As above, initialize and record new page if we got one */
211  if (extended)
212  brin_initialize_empty_new_buffer(idxrel, newbuf);
213  UnlockReleaseBuffer(newbuf);
214  if (extended)
215  FreeSpaceMapVacuumRange(idxrel, newblk, newblk + 1);
216  }
217 
218  return true;
219  }
220  else if (newbuf == InvalidBuffer)
221  {
222  /*
223  * Not enough space, but caller said that there was. Tell them to
224  * start over.
225  */
227  return false;
228  }
229  else
230  {
231  /*
232  * Not enough free space on the oldpage. Put the new tuple on the new
233  * page, and update the revmap.
234  */
235  Page newpage = BufferGetPage(newbuf);
236  Buffer revmapbuf;
237  ItemPointerData newtid;
238  OffsetNumber newoff;
239  Size freespace = 0;
240 
241  revmapbuf = brinLockRevmapPageForUpdate(revmap, heapBlk);
242 
244 
245  /*
246  * We need to initialize the page if it's newly obtained. Note we
247  * will WAL-log the initialization as part of the update, so we don't
248  * need to do that here.
249  */
250  if (extended)
252 
253  PageIndexTupleDeleteNoCompact(oldpage, oldoff);
254  newoff = PageAddItem(newpage, (Item) unconstify(BrinTuple *, newtup), newsz,
255  InvalidOffsetNumber, false, false);
256  if (newoff == InvalidOffsetNumber)
257  elog(ERROR, "failed to add BRIN tuple to new page");
258  MarkBufferDirty(oldbuf);
259  MarkBufferDirty(newbuf);
260 
261  /* needed to update FSM below */
262  if (extended)
263  freespace = br_page_get_freespace(newpage);
264 
265  ItemPointerSet(&newtid, newblk, newoff);
266  brinSetHeapBlockItemptr(revmapbuf, pagesPerRange, heapBlk, newtid);
267  MarkBufferDirty(revmapbuf);
268 
269  /* XLOG stuff */
270  if (RelationNeedsWAL(idxrel))
271  {
272  xl_brin_update xlrec;
273  XLogRecPtr recptr;
274  uint8 info;
275 
276  info = XLOG_BRIN_UPDATE | (extended ? XLOG_BRIN_INIT_PAGE : 0);
277 
278  xlrec.insert.offnum = newoff;
279  xlrec.insert.heapBlk = heapBlk;
280  xlrec.insert.pagesPerRange = pagesPerRange;
281  xlrec.oldOffnum = oldoff;
282 
283  XLogBeginInsert();
284 
285  /* new page */
286  XLogRegisterData((char *) &xlrec, SizeOfBrinUpdate);
287 
288  XLogRegisterBuffer(0, newbuf, REGBUF_STANDARD | (extended ? REGBUF_WILL_INIT : 0));
289  XLogRegisterBufData(0, (char *) unconstify(BrinTuple *, newtup), newsz);
290 
291  /* revmap page */
292  XLogRegisterBuffer(1, revmapbuf, 0);
293 
294  /* old page */
296 
297  recptr = XLogInsert(RM_BRIN_ID, info);
298 
299  PageSetLSN(oldpage, recptr);
300  PageSetLSN(newpage, recptr);
301  PageSetLSN(BufferGetPage(revmapbuf), recptr);
302  }
303 
305 
306  LockBuffer(revmapbuf, BUFFER_LOCK_UNLOCK);
308  UnlockReleaseBuffer(newbuf);
309 
310  if (extended)
311  {
312  RecordPageWithFreeSpace(idxrel, newblk, freespace);
313  FreeSpaceMapVacuumRange(idxrel, newblk, newblk + 1);
314  }
315 
316  return true;
317  }
318 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:361
BlockNumber heapBlk
Definition: brin_xlog.h:65
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, Size spaceAvail)
Definition: freespace.c:181
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
OffsetNumber offnum
Definition: brin_xlog.h:104
unsigned char uint8
Definition: c.h:357
Pointer Item
Definition: item.h:17
#define InvalidBuffer
Definition: buf.h:25
Buffer brinLockRevmapPageForUpdate(BrinRevmap *revmap, BlockNumber heapBlk)
Definition: brin_revmap.c:137
#define REGBUF_WILL_INIT
Definition: xloginsert.h:33
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
int errcode(int sqlerrcode)
Definition: elog.c:608
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:357
uint16 OffsetNumber
Definition: off.h:24
#define SizeOfBrinUpdate
Definition: brin_xlog.h:95
#define XLOG_BRIN_UPDATE
Definition: brin_xlog.h:33
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3388
#define ERROR
Definition: elog.h:43
#define BRIN_PAGETYPE_REGULAR
Definition: brin_page.h:53
void brinRevmapExtend(BrinRevmap *revmap, BlockNumber heapBlk)
Definition: brin_revmap.c:115
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1065
bool brin_tuples_equal(const BrinTuple *a, Size alen, const BrinTuple *b, Size blen)
Definition: brin_tuple.c:339
BlockNumber pagesPerRange
Definition: brin_xlog.h:68
#define REGBUF_STANDARD
Definition: xloginsert.h:35
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:908
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define ereport(elevel, rest)
Definition: elog.h:141
bool brin_can_do_samepage_update(Buffer buffer, Size origsz, Size newsz)
Definition: brin_pageops.c:324
#define unconstify(underlying_type, expr)
Definition: c.h:1194
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
#define XLOG_BRIN_INIT_PAGE
Definition: brin_xlog.h:43
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
#define InvalidOffsetNumber
Definition: off.h:26
xl_brin_insert insert
Definition: brin_xlog.h:92
void PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum)
Definition: bufpage.c:957
#define BrinMaxItemSize
Definition: brin_pageops.c:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:739
#define ItemIdIsNormal(itemId)
Definition: itemid.h:99
#define SizeOfBrinSamepageUpdate
Definition: brin_xlog.h:107
size_t Size
Definition: c.h:467
#define XLOG_BRIN_SAMEPAGE_UPDATE
Definition: brin_xlog.h:34
#define InvalidBlockNumber
Definition: block.h:33
OffsetNumber offnum
Definition: brin_xlog.h:71
static void brin_initialize_empty_new_buffer(Relation idxrel, Buffer buffer)
Definition: brin_pageops.c:876
#define MAXALIGN(LEN)
Definition: c.h:692
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define RelationNeedsWAL(relation)
Definition: rel.h:524
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define elog(elevel,...)
Definition: elog.h:228
static Buffer brin_getinsertbuffer(Relation irel, Buffer oldbuf, Size itemsz, bool *extended)
Definition: brin_pageops.c:686
#define BRIN_EVACUATE_PAGE
Definition: brin_page.h:60
#define BrinPageFlags(page)
Definition: brin_page.h:46
void brinSetHeapBlockItemptr(Buffer buf, BlockNumber pagesPerRange, BlockNumber heapBlk, ItemPointerData tid)
Definition: brin_revmap.c:158
void XLogBeginInsert(void)
Definition: xloginsert.c:120
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
OffsetNumber oldOffnum
Definition: brin_xlog.h:90
int Buffer
Definition: buf.h:23
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:352
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:476

◆ brin_evacuate_page()

void brin_evacuate_page ( Relation  idxRel,
BlockNumber  pagesPerRange,
BrinRevmap revmap,
Buffer  buf 
)

Definition at line 560 of file brin_pageops.c.

References Assert, brin_copy_tuple(), brin_doupdate(), BRIN_EVACUATE_PAGE, BRIN_IS_REGULAR_PAGE, BrinPageFlags, BrinTuple::bt_blkno, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetPage, CHECK_FOR_INTERRUPTS, FirstOffsetNumber, ItemIdGetLength, ItemIdIsUsed, LockBuffer(), PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, and UnlockReleaseBuffer().

Referenced by revmap_physical_extend().

562 {
563  OffsetNumber off;
564  OffsetNumber maxoff;
565  Page page;
566  BrinTuple *btup = NULL;
567  Size btupsz = 0;
568 
569  page = BufferGetPage(buf);
570 
572 
573  maxoff = PageGetMaxOffsetNumber(page);
574  for (off = FirstOffsetNumber; off <= maxoff; off++)
575  {
576  BrinTuple *tup;
577  Size sz;
578  ItemId lp;
579 
581 
582  lp = PageGetItemId(page, off);
583  if (ItemIdIsUsed(lp))
584  {
585  sz = ItemIdGetLength(lp);
586  tup = (BrinTuple *) PageGetItem(page, lp);
587  tup = brin_copy_tuple(tup, sz, btup, &btupsz);
588 
590 
591  if (!brin_doupdate(idxRel, pagesPerRange, revmap, tup->bt_blkno,
592  buf, off, tup, sz, tup, sz, false))
593  off--; /* retry */
594 
596 
597  /* It's possible that someone extended the revmap over this page */
598  if (!BRIN_IS_REGULAR_PAGE(page))
599  break;
600  }
601  }
602 
604 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
BrinTuple * brin_copy_tuple(BrinTuple *tuple, Size len, BrinTuple *dest, Size *destsz)
Definition: brin_tuple.c:320
#define ItemIdIsUsed(itemId)
Definition: itemid.h:92
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
bool brin_doupdate(Relation idxrel, BlockNumber pagesPerRange, BrinRevmap *revmap, BlockNumber heapBlk, Buffer oldbuf, OffsetNumber oldoff, const BrinTuple *origtup, Size origsz, const BrinTuple *newtup, Size newsz, bool samepage)
Definition: brin_pageops.c:54
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:357
uint16 OffsetNumber
Definition: off.h:24
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3388
static char * buf
Definition: pg_test_fsync.c:67
#define FirstOffsetNumber
Definition: off.h:27
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
BlockNumber bt_blkno
Definition: brin_tuple.h:57
#define Assert(condition)
Definition: c.h:739
size_t Size
Definition: c.h:467
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:87
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define BRIN_EVACUATE_PAGE
Definition: brin_page.h:60
#define BrinPageFlags(page)
Definition: brin_page.h:46
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78

◆ brin_getinsertbuffer()

static Buffer brin_getinsertbuffer ( Relation  irel,
Buffer  oldbuf,
Size  itemsz,
bool extended 
)
static

Definition at line 686 of file brin_pageops.c.

References Assert, br_page_get_freespace(), BRIN_elog, brin_initialize_empty_new_buffer(), BRIN_IS_REGULAR_PAGE, BrinMaxItemSize, buf, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, BufferIsValid, CHECK_FOR_INTERRUPTS, DEBUG2, ereport, errcode(), errmsg(), ERROR, ExclusiveLock, FreeSpaceMapVacuumRange(), GetPageWithFreeSpace(), InvalidBlockNumber, InvalidBuffer, LockBuffer(), LockRelationForExtension(), P_NEW, ReadBuffer(), RecordAndGetPageWithFreeSpace(), RELATION_IS_LOCAL, RelationGetRelationName, RelationGetTargetBlock, RelationSetTargetBlock, ReleaseBuffer(), UnlockRelationForExtension(), and UnlockReleaseBuffer().

Referenced by brin_doinsert(), and brin_doupdate().

688 {
689  BlockNumber oldblk;
690  BlockNumber newblk;
691  Page page;
692  Size freespace;
693 
694  /* callers must have checked */
695  Assert(itemsz <= BrinMaxItemSize);
696 
697  if (BufferIsValid(oldbuf))
698  oldblk = BufferGetBlockNumber(oldbuf);
699  else
700  oldblk = InvalidBlockNumber;
701 
702  /* Choose initial target page, re-using existing target if known */
703  newblk = RelationGetTargetBlock(irel);
704  if (newblk == InvalidBlockNumber)
705  newblk = GetPageWithFreeSpace(irel, itemsz);
706 
707  /*
708  * Loop until we find a page with sufficient free space. By the time we
709  * return to caller out of this loop, both buffers are valid and locked;
710  * if we have to restart here, neither page is locked and newblk isn't
711  * pinned (if it's even valid).
712  */
713  for (;;)
714  {
715  Buffer buf;
716  bool extensionLockHeld = false;
717 
719 
720  *extended = false;
721 
722  if (newblk == InvalidBlockNumber)
723  {
724  /*
725  * There's not enough free space in any existing index page,
726  * according to the FSM: extend the relation to obtain a shiny new
727  * page.
728  */
729  if (!RELATION_IS_LOCAL(irel))
730  {
732  extensionLockHeld = true;
733  }
734  buf = ReadBuffer(irel, P_NEW);
735  newblk = BufferGetBlockNumber(buf);
736  *extended = true;
737 
738  BRIN_elog((DEBUG2, "brin_getinsertbuffer: extending to page %u",
739  BufferGetBlockNumber(buf)));
740  }
741  else if (newblk == oldblk)
742  {
743  /*
744  * There's an odd corner-case here where the FSM is out-of-date,
745  * and gave us the old page.
746  */
747  buf = oldbuf;
748  }
749  else
750  {
751  buf = ReadBuffer(irel, newblk);
752  }
753 
754  /*
755  * We lock the old buffer first, if it's earlier than the new one; but
756  * then we need to check that it hasn't been turned into a revmap page
757  * concurrently. If we detect that that happened, give up and tell
758  * caller to start over.
759  */
760  if (BufferIsValid(oldbuf) && oldblk < newblk)
761  {
763  if (!BRIN_IS_REGULAR_PAGE(BufferGetPage(oldbuf)))
764  {
766 
767  /*
768  * It is possible that the new page was obtained from
769  * extending the relation. In that case, we must be sure to
770  * record it in the FSM before leaving, because otherwise the
771  * space would be lost forever. However, we cannot let an
772  * uninitialized page get in the FSM, so we need to initialize
773  * it first.
774  */
775  if (*extended)
777 
778  if (extensionLockHeld)
780 
781  ReleaseBuffer(buf);
782 
783  if (*extended)
784  {
785  FreeSpaceMapVacuumRange(irel, newblk, newblk + 1);
786  /* shouldn't matter, but don't confuse caller */
787  *extended = false;
788  }
789 
790  return InvalidBuffer;
791  }
792  }
793 
795 
796  if (extensionLockHeld)
798 
799  page = BufferGetPage(buf);
800 
801  /*
802  * We have a new buffer to insert into. Check that the new page has
803  * enough free space, and return it if it does; otherwise start over.
804  * (br_page_get_freespace also checks that the FSM didn't hand us a
805  * page that has since been repurposed for the revmap.)
806  */
807  freespace = *extended ?
809  if (freespace >= itemsz)
810  {
811  RelationSetTargetBlock(irel, newblk);
812 
813  /*
814  * Lock the old buffer if not locked already. Note that in this
815  * case we know for sure it's a regular page: it's later than the
816  * new page we just got, which is not a revmap page, and revmap
817  * pages are always consecutive.
818  */
819  if (BufferIsValid(oldbuf) && oldblk > newblk)
820  {
823  }
824 
825  return buf;
826  }
827 
828  /* This page is no good. */
829 
830  /*
831  * If an entirely new page does not contain enough free space for the
832  * new item, then surely that item is oversized. Complain loudly; but
833  * first make sure we initialize the page and record it as free, for
834  * next time.
835  */
836  if (*extended)
837  {
839  /* since this should not happen, skip FreeSpaceMapVacuum */
840 
841  ereport(ERROR,
842  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
843  errmsg("index row size %zu exceeds maximum %zu for index \"%s\"",
844  itemsz, freespace, RelationGetRelationName(irel))));
845  return InvalidBuffer; /* keep compiler quiet */
846  }
847 
848  if (newblk != oldblk)
849  UnlockReleaseBuffer(buf);
850  if (BufferIsValid(oldbuf) && oldblk <= newblk)
852 
853  /*
854  * Update the FSM with the new, presumably smaller, freespace value
855  * for this page, then search for a new target page.
856  */
857  newblk = RecordAndGetPageWithFreeSpace(irel, newblk, freespace, itemsz);
858  }
859 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
#define BRIN_elog(args)
Definition: brin_internal.h:81
#define ExclusiveLock
Definition: lockdefs.h:44
#define RELATION_IS_LOCAL(relation)
Definition: rel.h:542
#define InvalidBuffer
Definition: buf.h:25
int errcode(int sqlerrcode)
Definition: elog.c:608
#define BRIN_IS_REGULAR_PAGE(page)
Definition: brin_page.h:57
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3365
#define P_NEW
Definition: bufmgr.h:81
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
#define RelationGetTargetBlock(relation)
Definition: rel.h:507
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3388
#define ERROR
Definition: elog.h:43
#define DEBUG2
Definition: elog.h:24
static char * buf
Definition: pg_test_fsync.c:67
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:908
#define RelationGetRelationName(relation)
Definition: rel.h:456
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define ereport(elevel, rest)
Definition: elog.h:141
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:402
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:452
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
#define BrinMaxItemSize
Definition: brin_pageops.c:29
#define Assert(condition)
Definition: c.h:739
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:596
#define RelationSetTargetBlock(relation, targblock)
Definition: rel.h:514
size_t Size
Definition: c.h:467
#define InvalidBlockNumber
Definition: block.h:33
static void brin_initialize_empty_new_buffer(Relation idxrel, Buffer buffer)
Definition: brin_pageops.c:876
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
int errmsg(const char *fmt,...)
Definition: elog.c:822
BlockNumber GetPageWithFreeSpace(Relation rel, Size spaceNeeded)
Definition: freespace.c:132
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
BlockNumber RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage, Size oldSpaceAvail, Size spaceNeeded)
Definition: freespace.c:149
int Buffer
Definition: buf.h:23
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:352
Pointer Page
Definition: bufpage.h:78

◆ brin_initialize_empty_new_buffer()

static void brin_initialize_empty_new_buffer ( Relation  idxrel,
Buffer  buffer 
)
static

Definition at line 876 of file brin_pageops.c.

References br_page_get_freespace(), BRIN_elog, brin_page_init(), BRIN_PAGETYPE_REGULAR, BufferGetBlockNumber(), BufferGetPage, DEBUG2, END_CRIT_SECTION, log_newpage_buffer(), MarkBufferDirty(), RecordPageWithFreeSpace(), and START_CRIT_SECTION.

Referenced by brin_doupdate(), brin_getinsertbuffer(), and brin_page_cleanup().

877 {
878  Page page;
879 
880  BRIN_elog((DEBUG2,
881  "brin_initialize_empty_new_buffer: initializing blank page %u",
882  BufferGetBlockNumber(buffer)));
883 
885  page = BufferGetPage(buffer);
887  MarkBufferDirty(buffer);
888  log_newpage_buffer(buffer, true);
890 
891  /*
892  * We update the FSM for this page, but this is not WAL-logged. This is
893  * acceptable because VACUUM will scan the index and update the FSM with
894  * pages whose FSM records were forgotten in a crash.
895  */
897  br_page_get_freespace(page));
898 }
#define BRIN_elog(args)
Definition: brin_internal.h:81
XLogRecPtr log_newpage_buffer(Buffer buffer, bool page_std)
Definition: xloginsert.c:1009
void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, Size spaceAvail)
Definition: freespace.c:181
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
#define BRIN_PAGETYPE_REGULAR
Definition: brin_page.h:53
#define DEBUG2
Definition: elog.h:24
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:908
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
Pointer Page
Definition: bufpage.h:78
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:476

◆ brin_metapage_init()

void brin_metapage_init ( Page  page,
BlockNumber  pagesPerRange,
uint16  version 
)

Definition at line 487 of file brin_pageops.c.

References BRIN_META_MAGIC, brin_page_init(), BRIN_PAGETYPE_META, BrinMetaPageData::brinMagic, BrinMetaPageData::brinVersion, BrinMetaPageData::lastRevmapPage, PageGetContents, and BrinMetaPageData::pagesPerRange.

Referenced by brin_xlog_createidx(), brinbuild(), and brinbuildempty().

488 {
489  BrinMetaPageData *metadata;
490 
492 
493  metadata = (BrinMetaPageData *) PageGetContents(page);
494 
495  metadata->brinMagic = BRIN_META_MAGIC;
496  metadata->brinVersion = version;
497  metadata->pagesPerRange = pagesPerRange;
498 
499  /*
500  * Note we cheat here a little. 0 is not a valid revmap block number
501  * (because it's the metapage buffer), but doing this enables the first
502  * revmap page to be created when the index is.
503  */
504  metadata->lastRevmapPage = 0;
505 
506  /*
507  * Set pd_lower just past the end of the metadata. This is essential,
508  * because without doing so, metadata will be lost if xlog.c compresses
509  * the page.
510  */
511  ((PageHeader) page)->pd_lower =
512  ((char *) metadata + sizeof(BrinMetaPageData)) - (char *) page;
513 }
uint32 brinVersion
Definition: brin_page.h:67
uint32 brinMagic
Definition: brin_page.h:66
#define BRIN_PAGETYPE_META
Definition: brin_page.h:51
BlockNumber lastRevmapPage
Definition: brin_page.h:69
#define PageGetContents(page)
Definition: bufpage.h:246
BlockNumber pagesPerRange
Definition: brin_page.h:68
PageHeaderData * PageHeader
Definition: bufpage.h:166
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:476
#define BRIN_META_MAGIC
Definition: brin_page.h:73

◆ brin_page_cleanup()

void brin_page_cleanup ( Relation  idxrel,
Buffer  buf 
)

Definition at line 620 of file brin_pageops.c.

References br_page_get_freespace(), brin_initialize_empty_new_buffer(), BRIN_IS_META_PAGE, BRIN_IS_REVMAP_PAGE, BUFFER_LOCK_EXCLUSIVE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, LockBuffer(), LockRelationForExtension(), PageIsNew, RecordPageWithFreeSpace(), ShareLock, and UnlockRelationForExtension().

Referenced by brin_vacuum_scan().

621 {
622  Page page = BufferGetPage(buf);
623 
624  /*
625  * If a page was left uninitialized, initialize it now; also record it in
626  * FSM.
627  *
628  * Somebody else might be extending the relation concurrently. To avoid
629  * re-initializing the page before they can grab the buffer lock, we
630  * acquire the extension lock momentarily. Since they hold the extension
631  * lock from before getting the page and after its been initialized, we're
632  * sure to see their initialization.
633  */
634  if (PageIsNew(page))
635  {
638 
640  if (PageIsNew(page))
641  {
644  return;
645  }
647  }
648 
649  /* Nothing to be done for non-regular index pages */
652  return;
653 
654  /* Measure free space and record it */
656  br_page_get_freespace(page));
657 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:86
void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, Size spaceAvail)
Definition: freespace.c:181
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:88
static char * buf
Definition: pg_test_fsync.c:67
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:908
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:402
#define BRIN_IS_META_PAGE(page)
Definition: brin_page.h:55
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:452
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3602
#define BRIN_IS_REVMAP_PAGE(page)
Definition: brin_page.h:56
static void brin_initialize_empty_new_buffer(Relation idxrel, Buffer buffer)
Definition: brin_pageops.c:876
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2613
#define PageIsNew(page)
Definition: bufpage.h:229
#define ShareLock
Definition: lockdefs.h:41
Pointer Page
Definition: bufpage.h:78

◆ brin_page_init()

void brin_page_init ( Page  page,
uint16  type 
)

Definition at line 476 of file brin_pageops.c.

References BrinPageType, PageInit(), and generate_unaccent_rules::type.

Referenced by brin_doinsert(), brin_doupdate(), brin_initialize_empty_new_buffer(), brin_metapage_init(), brin_xlog_insert_update(), brin_xlog_revmap_extend(), and revmap_physical_extend().

477 {
478  PageInit(page, BLCKSZ, sizeof(BrinSpecialSpace));
479 
480  BrinPageType(page) = type;
481 }
#define BrinPageType(page)
Definition: brin_page.h:42
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42

◆ brin_start_evacuating_page()

bool brin_start_evacuating_page ( Relation  idxRel,
Buffer  buf 
)

Definition at line 525 of file brin_pageops.c.

References BRIN_EVACUATE_PAGE, BrinPageFlags, BufferGetPage, FirstOffsetNumber, ItemIdIsUsed, MarkBufferDirtyHint(), PageGetItemId, PageGetMaxOffsetNumber, and PageIsNew.

Referenced by revmap_physical_extend().

526 {
527  OffsetNumber off;
528  OffsetNumber maxoff;
529  Page page;
530 
531  page = BufferGetPage(buf);
532 
533  if (PageIsNew(page))
534  return false;
535 
536  maxoff = PageGetMaxOffsetNumber(page);
537  for (off = FirstOffsetNumber; off <= maxoff; off++)
538  {
539  ItemId lp;
540 
541  lp = PageGetItemId(page, off);
542  if (ItemIdIsUsed(lp))
543  {
544  /* prevent other backends from adding more stuff to this page */
546  MarkBufferDirtyHint(buf, true);
547 
548  return true;
549  }
550  }
551  return false;
552 }
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3435
#define ItemIdIsUsed(itemId)
Definition: itemid.h:92
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:357
uint16 OffsetNumber
Definition: off.h:24
static char * buf
Definition: pg_test_fsync.c:67
#define FirstOffsetNumber
Definition: off.h:27
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
#define PageIsNew(page)
Definition: bufpage.h:229
#define BRIN_EVACUATE_PAGE
Definition: brin_page.h:60
#define BrinPageFlags(page)
Definition: brin_page.h:46
Pointer Page
Definition: bufpage.h:78