PostgreSQL Source Code  git master
brin_pageops.h File Reference
Include dependency graph for brin_pageops.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

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)
 

Function Documentation

◆ brin_can_do_samepage_update()

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

Definition at line 325 of file brin_pageops.c.

References BufferGetPage, and PageGetExactFreeSpace().

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

326 {
327  return
328  ((newsz <= origsz) ||
329  PageGetExactFreeSpace(BufferGetPage(buffer)) >= (newsz - origsz));
330 }
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
Size PageGetExactFreeSpace(Page page)
Definition: bufpage.c:629

◆ brin_doinsert()

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

Definition at line 344 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().

347 {
348  Page page;
349  BlockNumber blk;
350  OffsetNumber off;
351  Size freespace = 0;
352  Buffer revmapbuf;
353  ItemPointerData tid;
354  bool extended;
355 
356  Assert(itemsz == MAXALIGN(itemsz));
357 
358  /* If the item is oversized, don't even bother. */
359  if (itemsz > BrinMaxItemSize)
360  {
361  ereport(ERROR,
362  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
363  errmsg("index row size %zu exceeds maximum %zu for index \"%s\"",
364  itemsz, BrinMaxItemSize, RelationGetRelationName(idxrel))));
365  return InvalidOffsetNumber; /* keep compiler quiet */
366  }
367 
368  /* Make sure the revmap is long enough to contain the entry we need */
369  brinRevmapExtend(revmap, heapBlk);
370 
371  /*
372  * Acquire lock on buffer supplied by caller, if any. If it doesn't have
373  * enough space, unpin it to obtain a new one below.
374  */
375  if (BufferIsValid(*buffer))
376  {
377  /*
378  * It's possible that another backend (or ourselves!) extended the
379  * revmap over the page we held a pin on, so we cannot assume that
380  * it's still a regular page.
381  */
384  {
387  }
388  }
389 
390  /*
391  * If we still don't have a usable buffer, have brin_getinsertbuffer
392  * obtain one for us.
393  */
394  if (!BufferIsValid(*buffer))
395  {
396  do
397  *buffer = brin_getinsertbuffer(idxrel, InvalidBuffer, itemsz, &extended);
398  while (!BufferIsValid(*buffer));
399  }
400  else
401  extended = false;
402 
403  /* Now obtain lock on revmap buffer */
404  revmapbuf = brinLockRevmapPageForUpdate(revmap, heapBlk);
405 
406  page = BufferGetPage(*buffer);
408 
409  /* Execute the actual insertion */
411  if (extended)
413  off = PageAddItem(page, (Item) tup, itemsz, InvalidOffsetNumber,
414  false, false);
415  if (off == InvalidOffsetNumber)
416  elog(ERROR, "failed to add BRIN tuple to new page");
418 
419  /* needed to update FSM below */
420  if (extended)
421  freespace = br_page_get_freespace(page);
422 
423  ItemPointerSet(&tid, blk, off);
424  brinSetHeapBlockItemptr(revmapbuf, pagesPerRange, heapBlk, tid);
425  MarkBufferDirty(revmapbuf);
426 
427  /* XLOG stuff */
428  if (RelationNeedsWAL(idxrel))
429  {
430  xl_brin_insert xlrec;
431  XLogRecPtr recptr;
432  uint8 info;
433 
434  info = XLOG_BRIN_INSERT | (extended ? XLOG_BRIN_INIT_PAGE : 0);
435  xlrec.heapBlk = heapBlk;
436  xlrec.pagesPerRange = pagesPerRange;
437  xlrec.offnum = off;
438 
439  XLogBeginInsert();
440  XLogRegisterData((char *) &xlrec, SizeOfBrinInsert);
441 
443  XLogRegisterBufData(0, (char *) tup, itemsz);
444 
445  XLogRegisterBuffer(1, revmapbuf, 0);
446 
447  recptr = XLogInsert(RM_BRIN_ID, info);
448 
449  PageSetLSN(page, recptr);
450  PageSetLSN(BufferGetPage(revmapbuf), recptr);
451  }
452 
454 
455  /* Tuple is firmly on buffer; we can release our locks */
457  LockBuffer(revmapbuf, BUFFER_LOCK_UNLOCK);
458 
459  BRIN_elog((DEBUG2, "inserted tuple (%u,%u) for range starting at %u",
460  blk, off, heapBlk));
461 
462  if (extended)
463  {
464  RecordPageWithFreeSpace(idxrel, blk, freespace);
465  FreeSpaceMapVacuumRange(idxrel, blk, blk + 1);
466  }
467 
468  return off;
469 }
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:87
#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:1450
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:213
#define END_CRIT_SECTION()
Definition: miscadmin.h:133
unsigned char uint8
Definition: c.h:323
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:32
#define START_CRIT_SECTION()
Definition: miscadmin.h:131
int errcode(int sqlerrcode)
Definition: elog.c:575
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
uint16 OffsetNumber
Definition: off.h:24
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#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:34
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:909
#define RelationGetRelationName(relation)
Definition: rel.h:441
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define ereport(elevel, rest)
Definition: elog.h:122
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:3546
#define InvalidOffsetNumber
Definition: off.h:26
#define BrinMaxItemSize
Definition: brin_pageops.c:30
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:699
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:215
size_t Size
Definition: c.h:433
OffsetNumber offnum
Definition: brin_xlog.h:71
#define MAXALIGN(LEN)
Definition: c.h:652
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define RelationNeedsWAL(relation)
Definition: rel.h:510
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
int errmsg(const char *fmt,...)
Definition: elog.c:797
static Buffer brin_getinsertbuffer(Relation irel, Buffer oldbuf, Size itemsz, bool *extended)
Definition: brin_pageops.c:687
#define elog
Definition: elog.h:219
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:364
int Buffer
Definition: buf.h:23
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:368
Pointer Page
Definition: bufpage.h:74
#define ItemPointerSet(pointer, blockNumber, offNum)
Definition: itemptr.h:127
void brin_page_init(Page page, uint16 type)
Definition: brin_pageops.c:477

◆ 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 55 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, 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().

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

◆ brin_evacuate_page()

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

Definition at line 561 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().

563 {
564  OffsetNumber off;
565  OffsetNumber maxoff;
566  Page page;
567  BrinTuple *btup = NULL;
568  Size btupsz = 0;
569 
570  page = BufferGetPage(buf);
571 
573 
574  maxoff = PageGetMaxOffsetNumber(page);
575  for (off = FirstOffsetNumber; off <= maxoff; off++)
576  {
577  BrinTuple *tup;
578  Size sz;
579  ItemId lp;
580 
582 
583  lp = PageGetItemId(page, off);
584  if (ItemIdIsUsed(lp))
585  {
586  sz = ItemIdGetLength(lp);
587  tup = (BrinTuple *) PageGetItem(page, lp);
588  tup = brin_copy_tuple(tup, sz, btup, &btupsz);
589 
591 
592  if (!brin_doupdate(idxRel, pagesPerRange, revmap, tup->bt_blkno,
593  buf, off, tup, sz, tup, sz, false))
594  off--; /* retry */
595 
597 
598  /* It's possible that someone extended the revmap over this page */
599  if (!BRIN_IS_REGULAR_PAGE(page))
600  break;
601  }
602  }
603 
605 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
BrinTuple * brin_copy_tuple(BrinTuple *tuple, Size len, BrinTuple *dest, Size *destsz)
Definition: brin_tuple.c:321
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#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:55
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
uint16 OffsetNumber
Definition: off.h:24
#define ItemIdGetLength(itemId)
Definition: itemid.h:58
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
static char * buf
Definition: pg_test_fsync.c:67
#define FirstOffsetNumber
Definition: off.h:27
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
BlockNumber bt_blkno
Definition: brin_tuple.h:57
#define Assert(condition)
Definition: c.h:699
size_t Size
Definition: c.h:433
#define BUFFER_LOCK_SHARE
Definition: bufmgr.h:88
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define BRIN_EVACUATE_PAGE
Definition: brin_page.h:60
#define BrinPageFlags(page)
Definition: brin_page.h:46
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74

◆ brin_metapage_init()

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

Definition at line 488 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().

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

◆ brin_page_cleanup()

void brin_page_cleanup ( Relation  idxrel,
Buffer  buf 
)

Definition at line 621 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().

622 {
623  Page page = BufferGetPage(buf);
624 
625  /*
626  * If a page was left uninitialized, initialize it now; also record it in
627  * FSM.
628  *
629  * Somebody else might be extending the relation concurrently. To avoid
630  * re-initializing the page before they can grab the buffer lock, we
631  * acquire the extension lock momentarily. Since they hold the extension
632  * lock from before getting the page and after its been initialized, we're
633  * sure to see their initialization.
634  */
635  if (PageIsNew(page))
636  {
639 
641  if (PageIsNew(page))
642  {
645  return;
646  }
648  }
649 
650  /* Nothing to be done for non-regular index pages */
653  return;
654 
655  /* Measure free space and record it */
657  br_page_get_freespace(page));
658 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, Size spaceAvail)
Definition: freespace.c:181
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
static char * buf
Definition: pg_test_fsync.c:67
static Size br_page_get_freespace(Page page)
Definition: brin_pageops.c:909
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
void LockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:332
#define BRIN_IS_META_PAGE(page)
Definition: brin_page.h:55
void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode)
Definition: lmgr.c:382
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3546
#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:877
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define PageIsNew(page)
Definition: bufpage.h:225
#define ShareLock
Definition: lockdefs.h:41
Pointer Page
Definition: bufpage.h:74

◆ brin_page_init()

void brin_page_init ( Page  page,
uint16  type 
)

Definition at line 477 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().

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

◆ brin_start_evacuating_page()

bool brin_start_evacuating_page ( Relation  idxRel,
Buffer  buf 
)

Definition at line 526 of file brin_pageops.c.

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

Referenced by revmap_physical_extend().

527 {
528  OffsetNumber off;
529  OffsetNumber maxoff;
530  Page page;
531 
532  page = BufferGetPage(buf);
533 
534  if (PageIsNew(page))
535  return false;
536 
537  maxoff = PageGetMaxOffsetNumber(page);
538  for (off = FirstOffsetNumber; off <= maxoff; off++)
539  {
540  ItemId lp;
541 
542  lp = PageGetItemId(page, off);
543  if (ItemIdIsUsed(lp))
544  {
545  /* prevent other backends from adding more stuff to this page */
547  MarkBufferDirtyHint(buf, true);
548 
549  return true;
550  }
551  }
552  return false;
553 }
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:3379
#define ItemIdIsUsed(itemId)
Definition: itemid.h:91
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
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:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
#define PageIsNew(page)
Definition: bufpage.h:225
#define BRIN_EVACUATE_PAGE
Definition: brin_page.h:60
#define BrinPageFlags(page)
Definition: brin_page.h:46
Pointer Page
Definition: bufpage.h:74