PostgreSQL Source Code  git master
gistxlog.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/gist_private.h"
#include "access/gistxlog.h"
#include "access/heapam_xlog.h"
#include "access/transam.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
#include "storage/procarray.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for gistxlog.c:

Go to the source code of this file.

Functions

static void gistRedoClearFollowRight (XLogReaderState *record, uint8 block_id)
 
static void gistRedoPageUpdateRecord (XLogReaderState *record)
 
static void gistRedoDeleteRecord (XLogReaderState *record)
 
static IndexTupledecodePageSplitRecord (char *begin, int len, int *n)
 
static void gistRedoPageSplitRecord (XLogReaderState *record)
 
static void gistRedoPageDelete (XLogReaderState *record)
 
static void gistRedoPageReuse (XLogReaderState *record)
 
void gist_redo (XLogReaderState *record)
 
void gist_xlog_startup (void)
 
void gist_xlog_cleanup (void)
 
void gist_mask (char *pagedata, BlockNumber blkno)
 
XLogRecPtr gistXLogSplit (bool page_is_leaf, SplitedPageLayout *dist, BlockNumber origrlink, GistNSN orignsn, Buffer leftchildbuf, bool markfollowright)
 
XLogRecPtr gistXLogPageDelete (Buffer buffer, FullTransactionId xid, Buffer parentBuffer, OffsetNumber downlinkOffset)
 
XLogRecPtr gistXLogAssignLSN (void)
 
void gistXLogPageReuse (Relation rel, BlockNumber blkno, FullTransactionId latestRemovedXid)
 
XLogRecPtr gistXLogUpdate (Buffer buffer, OffsetNumber *todelete, int ntodelete, IndexTuple *itup, int ituplen, Buffer leftchildbuf)
 
XLogRecPtr gistXLogDelete (Buffer buffer, OffsetNumber *todelete, int ntodelete, TransactionId latestRemovedXid)
 

Variables

static MemoryContext opCtx
 

Function Documentation

◆ decodePageSplitRecord()

static IndexTuple* decodePageSplitRecord ( char *  begin,
int  len,
int *  n 
)
static

Definition at line 229 of file gistxlog.c.

References Assert, i, IndexTupleSize, and palloc().

Referenced by gistRedoPageSplitRecord().

230 {
231  char *ptr;
232  int i = 0;
233  IndexTuple *tuples;
234 
235  /* extract the number of tuples */
236  memcpy(n, begin, sizeof(int));
237  ptr = begin + sizeof(int);
238 
239  tuples = palloc(*n * sizeof(IndexTuple));
240 
241  for (i = 0; i < *n; i++)
242  {
243  Assert(ptr - begin < len);
244  tuples[i] = (IndexTuple) ptr;
245  ptr += IndexTupleSize((IndexTuple) ptr);
246  }
247  Assert(ptr - begin == len);
248 
249  return tuples;
250 }
IndexTupleData * IndexTuple
Definition: itup.h:53
#define Assert(condition)
Definition: c.h:746
void * palloc(Size size)
Definition: mcxt.c:950
int i
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ gist_mask()

void gist_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 478 of file gistxlog.c.

References GistClearPageHasGarbage, GistMarkFollowRight, GistPageIsLeaf, GistPageSetNSN, mask_lp_flags(), MASK_MARKER, mask_page_hint_bits(), mask_page_lsn_and_checksum(), mask_unused_space(), and GistSortedBuildPageState::page.

479 {
480  Page page = (Page) pagedata;
481 
483 
484  mask_page_hint_bits(page);
485  mask_unused_space(page);
486 
487  /*
488  * NSN is nothing but a special purpose LSN. Hence, mask it for the same
489  * reason as mask_page_lsn_and_checksum.
490  */
491  GistPageSetNSN(page, (uint64) MASK_MARKER);
492 
493  /*
494  * We update F_FOLLOW_RIGHT flag on the left child after writing WAL
495  * record. Hence, mask this flag. See gistplacetopage() for details.
496  */
497  GistMarkFollowRight(page);
498 
499  if (GistPageIsLeaf(page))
500  {
501  /*
502  * In gist leaf pages, it is possible to modify the LP_FLAGS without
503  * emitting any WAL record. Hence, mask the line pointer flags. See
504  * gistkillitems() for details.
505  */
506  mask_lp_flags(page);
507  }
508 
509  /*
510  * During gist redo, we never mark a page as garbage. Hence, mask it to
511  * ignore any differences.
512  */
514 }
#define GistClearPageHasGarbage(page)
Definition: gist.h:172
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
#define GistPageSetNSN(page, val)
Definition: gist.h:179
void mask_unused_space(Page page)
Definition: bufmask.c:71
#define MASK_MARKER
Definition: bufmask.h:24
#define GistPageIsLeaf(page)
Definition: gist.h:161
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
#define GistMarkFollowRight(page)
Definition: gist.h:175
void mask_lp_flags(Page page)
Definition: bufmask.c:95
Pointer Page
Definition: bufpage.h:78

◆ gist_redo()

void gist_redo ( XLogReaderState record)

Definition at line 422 of file gistxlog.c.

References elog, gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageReuse(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), MemoryContextReset(), MemoryContextSwitchTo(), PANIC, XLOG_GIST_ASSIGN_LSN, XLOG_GIST_DELETE, XLOG_GIST_PAGE_DELETE, XLOG_GIST_PAGE_REUSE, XLOG_GIST_PAGE_SPLIT, XLOG_GIST_PAGE_UPDATE, XLogRecGetInfo, and XLR_INFO_MASK.

423 {
424  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
425  MemoryContext oldCxt;
426 
427  /*
428  * GiST indexes do not require any conflict processing. NB: If we ever
429  * implement a similar optimization we have in b-tree, and remove killed
430  * tuples outside VACUUM, we'll need to handle that here.
431  */
432 
433  oldCxt = MemoryContextSwitchTo(opCtx);
434  switch (info)
435  {
437  gistRedoPageUpdateRecord(record);
438  break;
439  case XLOG_GIST_DELETE:
440  gistRedoDeleteRecord(record);
441  break;
443  gistRedoPageReuse(record);
444  break;
446  gistRedoPageSplitRecord(record);
447  break;
449  gistRedoPageDelete(record);
450  break;
452  /* nop. See gistGetFakeLSN(). */
453  break;
454  default:
455  elog(PANIC, "gist_redo: unknown op code %u", info);
456  }
457 
458  MemoryContextSwitchTo(oldCxt);
460 }
static void gistRedoPageUpdateRecord(XLogReaderState *record)
Definition: gistxlog.c:72
static void gistRedoPageReuse(XLogReaderState *record)
Definition: gistxlog.c:382
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned char uint8
Definition: c.h:373
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:137
#define PANIC
Definition: elog.h:53
static void gistRedoPageDelete(XLogReaderState *record)
Definition: gistxlog.c:348
#define XLOG_GIST_PAGE_SPLIT
Definition: gistxlog.h:25
static void gistRedoPageSplitRecord(XLogReaderState *record)
Definition: gistxlog.c:253
#define XLOG_GIST_DELETE
Definition: gistxlog.h:21
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:305
#define XLOG_GIST_PAGE_REUSE
Definition: gistxlog.h:23
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define XLOG_GIST_PAGE_DELETE
Definition: gistxlog.h:28
static void gistRedoDeleteRecord(XLogReaderState *record)
Definition: gistxlog.c:174
#define elog(elevel,...)
Definition: elog.h:214
static MemoryContext opCtx
Definition: gistxlog.c:28
#define XLOG_GIST_PAGE_UPDATE
Definition: gistxlog.h:20
#define XLOG_GIST_ASSIGN_LSN
Definition: gistxlog.h:29

◆ gist_xlog_cleanup()

void gist_xlog_cleanup ( void  )

Definition at line 469 of file gistxlog.c.

References MemoryContextDelete().

470 {
472 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
static MemoryContext opCtx
Definition: gistxlog.c:28

◆ gist_xlog_startup()

void gist_xlog_startup ( void  )

Definition at line 463 of file gistxlog.c.

References createTempGistContext().

464 {
466 }
MemoryContext createTempGistContext(void)
Definition: gist.c:119
static MemoryContext opCtx
Definition: gistxlog.c:28

◆ gistRedoClearFollowRight()

static void gistRedoClearFollowRight ( XLogReaderState record,
uint8  block_id 
)
static

Definition at line 42 of file gistxlog.c.

References generate_unaccent_rules::action, BLK_NEEDS_REDO, BLK_RESTORED, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, GistClearFollowRight, GistPageSetNSN, MarkBufferDirty(), GistSortedBuildPageState::page, PageSetLSN, UnlockReleaseBuffer(), and XLogReadBufferForRedo().

Referenced by gistRedoPageSplitRecord(), and gistRedoPageUpdateRecord().

43 {
44  XLogRecPtr lsn = record->EndRecPtr;
45  Buffer buffer;
46  Page page;
48 
49  /*
50  * Note that we still update the page even if it was restored from a full
51  * page image, because the updated NSN is not included in the image.
52  */
53  action = XLogReadBufferForRedo(record, block_id, &buffer);
54  if (action == BLK_NEEDS_REDO || action == BLK_RESTORED)
55  {
56  page = BufferGetPage(buffer);
57 
58  GistPageSetNSN(page, lsn);
60 
61  PageSetLSN(page, lsn);
62  MarkBufferDirty(buffer);
63  }
64  if (BufferIsValid(buffer))
65  UnlockReleaseBuffer(buffer);
66 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1469
#define GistPageSetNSN(page, val)
Definition: gist.h:179
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3534
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define GistClearFollowRight(page)
Definition: gist.h:176
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:293
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRedoAction
Definition: xlogutils.h:27
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78

◆ gistRedoDeleteRecord()

static void gistRedoDeleteRecord ( XLogReaderState record)
static

Definition at line 174 of file gistxlog.c.

References BLK_NEEDS_REDO, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, GistClearPageHasGarbage, GistMarkTuplesDeleted, InHotStandby, gistxlogDelete::latestRemovedXid, MarkBufferDirty(), gistxlogDelete::ntodelete, GistSortedBuildPageState::page, PageIndexMultiDelete(), PageSetLSN, ResolveRecoveryConflictWithSnapshot(), SizeOfGistxlogDelete, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockTag(), XLogRecGetData, and XLogRecGetDataLen.

Referenced by gist_redo().

175 {
176  XLogRecPtr lsn = record->EndRecPtr;
177  gistxlogDelete *xldata = (gistxlogDelete *) XLogRecGetData(record);
178  Buffer buffer;
179  Page page;
180 
181  /*
182  * If we have any conflict processing to do, it must happen before we
183  * update the page.
184  *
185  * GiST delete records can conflict with standby queries. You might think
186  * that vacuum records would conflict as well, but we've handled that
187  * already. XLOG_HEAP2_CLEANUP_INFO records provide the highest xid
188  * cleaned by the vacuum of the heap and so we can resolve any conflicts
189  * just once when that arrives. After that we know that no conflicts
190  * exist from individual gist vacuum records on that index.
191  */
192  if (InHotStandby)
193  {
194  RelFileNode rnode;
195 
196  XLogRecGetBlockTag(record, 0, &rnode, NULL, NULL);
197 
199  }
200 
201  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
202  {
203  page = (Page) BufferGetPage(buffer);
204 
206  {
207  OffsetNumber *todelete;
208 
209  todelete = (OffsetNumber *) ((char *) xldata + SizeOfGistxlogDelete);
210 
211  PageIndexMultiDelete(page, todelete, xldata->ntodelete);
212  }
213 
215  GistMarkTuplesDeleted(page);
216 
217  PageSetLSN(page, lsn);
218  MarkBufferDirty(buffer);
219  }
220 
221  if (BufferIsValid(buffer))
222  UnlockReleaseBuffer(buffer);
223 }
#define GistClearPageHasGarbage(page)
Definition: gist.h:172
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1469
#define GistMarkTuplesDeleted(page)
Definition: gist.h:167
#define InHotStandby
Definition: xlog.h:74
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3534
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:311
uint16 ntodelete
Definition: gistxlog.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1498
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:293
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:1036
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define SizeOfGistxlogDelete
Definition: gistxlog.h:60
TransactionId latestRemovedXid
Definition: gistxlog.h:52
void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
Definition: standby.c:304
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78

◆ gistRedoPageDelete()

static void gistRedoPageDelete ( XLogReaderState record)
static

Definition at line 348 of file gistxlog.c.

References BLK_NEEDS_REDO, BufferGetPage, BufferIsValid, gistxlogPageDelete::deleteXid, gistxlogPageDelete::downlinkOffset, XLogReaderState::EndRecPtr, GistPageSetDeleted(), MarkBufferDirty(), GistSortedBuildPageState::page, PageIndexTupleDelete(), PageSetLSN, UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by gist_redo().

349 {
350  XLogRecPtr lsn = record->EndRecPtr;
352  Buffer parentBuffer;
353  Buffer leafBuffer;
354 
355  if (XLogReadBufferForRedo(record, 0, &leafBuffer) == BLK_NEEDS_REDO)
356  {
357  Page page = (Page) BufferGetPage(leafBuffer);
358 
359  GistPageSetDeleted(page, xldata->deleteXid);
360 
361  PageSetLSN(page, lsn);
362  MarkBufferDirty(leafBuffer);
363  }
364 
365  if (XLogReadBufferForRedo(record, 1, &parentBuffer) == BLK_NEEDS_REDO)
366  {
367  Page page = (Page) BufferGetPage(parentBuffer);
368 
369  PageIndexTupleDelete(page, xldata->downlinkOffset);
370 
371  PageSetLSN(page, lsn);
372  MarkBufferDirty(parentBuffer);
373  }
374 
375  if (BufferIsValid(parentBuffer))
376  UnlockReleaseBuffer(parentBuffer);
377  if (BufferIsValid(leafBuffer))
378  UnlockReleaseBuffer(leafBuffer);
379 }
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:927
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1469
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
FullTransactionId deleteXid
Definition: gistxlog.h:87
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3534
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
static void GistPageSetDeleted(Page page, FullTransactionId deletexid)
Definition: gist.h:196
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:293
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78
OffsetNumber downlinkOffset
Definition: gistxlog.h:88

◆ gistRedoPageReuse()

static void gistRedoPageReuse ( XLogReaderState record)
static

Definition at line 382 of file gistxlog.c.

References InHotStandby, gistxlogPageReuse::latestRemovedFullXid, MaxTransactionId, gistxlogPageReuse::node, ReadNextFullTransactionId(), ResolveRecoveryConflictWithSnapshot(), U64FromFullTransactionId, XidFromFullTransactionId, and XLogRecGetData.

Referenced by gist_redo().

383 {
385 
386  /*
387  * PAGE_REUSE records exist to provide a conflict point when we reuse
388  * pages in the index via the FSM. That's all they do though.
389  *
390  * latestRemovedXid was the page's deleteXid. The
391  * GlobalVisIsRemovableFullXid(deleteXid) test in gistPageRecyclable()
392  * conceptually mirrors the PGPROC->xmin > limitXmin test in
393  * GetConflictingVirtualXIDs(). Consequently, one XID value achieves the
394  * same exclusion effect on primary and standby.
395  */
396  if (InHotStandby)
397  {
398  FullTransactionId latestRemovedFullXid = xlrec->latestRemovedFullXid;
400  uint64 diff;
401 
402  /*
403  * ResolveRecoveryConflictWithSnapshot operates on 32-bit
404  * TransactionIds, so truncate the logged FullTransactionId. If the
405  * logged value is very old, so that XID wrap-around already happened
406  * on it, there can't be any snapshots that still see it.
407  */
408  diff = U64FromFullTransactionId(nextXid) -
409  U64FromFullTransactionId(latestRemovedFullXid);
410  if (diff < MaxTransactionId / 2)
411  {
412  TransactionId latestRemovedXid;
413 
414  latestRemovedXid = XidFromFullTransactionId(latestRemovedFullXid);
415  ResolveRecoveryConflictWithSnapshot(latestRemovedXid,
416  xlrec->node);
417  }
418  }
419 }
uint32 TransactionId
Definition: c.h:521
#define InHotStandby
Definition: xlog.h:74
RelFileNode node
Definition: gistxlog.h:100
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
FullTransactionId ReadNextFullTransactionId(void)
Definition: varsup.c:261
#define MaxTransactionId
Definition: transam.h:35
#define U64FromFullTransactionId(x)
Definition: transam.h:49
void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
Definition: standby.c:304
FullTransactionId latestRemovedFullXid
Definition: gistxlog.h:102

◆ gistRedoPageSplitRecord()

static void gistRedoPageSplitRecord ( XLogReaderState record)
static

Definition at line 253 of file gistxlog.c.

References Assert, BufferGetPage, decodePageSplitRecord(), XLogReaderState::EndRecPtr, F_LEAF, FirstOffsetNumber, GIST_ROOT_BLKNO, GistClearFollowRight, gistfillbuffer(), GISTInitBuffer(), GistMarkFollowRight, GistPageGetOpaque, GistPageSetNSN, gistRedoClearFollowRight(), i, InvalidBlockNumber, InvalidBuffer, MarkBufferDirty(), gistxlogPageSplit::markfollowright, gistxlogPageSplit::npage, gistxlogPageSplit::origleaf, gistxlogPageSplit::orignsn, gistxlogPageSplit::origrlink, GistSortedBuildPageState::page, PageSetLSN, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogRecGetBlockData(), XLogRecGetBlockTag(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by gist_redo().

254 {
255  XLogRecPtr lsn = record->EndRecPtr;
256  gistxlogPageSplit *xldata = (gistxlogPageSplit *) XLogRecGetData(record);
257  Buffer firstbuffer = InvalidBuffer;
258  Buffer buffer;
259  Page page;
260  int i;
261  bool isrootsplit = false;
262 
263  /*
264  * We must hold lock on the first-listed page throughout the action,
265  * including while updating the left child page (if any). We can unlock
266  * remaining pages in the list as soon as they've been written, because
267  * there is no path for concurrent queries to reach those pages without
268  * first visiting the first-listed page.
269  */
270 
271  /* loop around all pages */
272  for (i = 0; i < xldata->npage; i++)
273  {
274  int flags;
275  char *data;
276  Size datalen;
277  int num;
278  BlockNumber blkno;
279  IndexTuple *tuples;
280 
281  XLogRecGetBlockTag(record, i + 1, NULL, NULL, &blkno);
282  if (blkno == GIST_ROOT_BLKNO)
283  {
284  Assert(i == 0);
285  isrootsplit = true;
286  }
287 
288  buffer = XLogInitBufferForRedo(record, i + 1);
289  page = (Page) BufferGetPage(buffer);
290  data = XLogRecGetBlockData(record, i + 1, &datalen);
291 
292  tuples = decodePageSplitRecord(data, datalen, &num);
293 
294  /* ok, clear buffer */
295  if (xldata->origleaf && blkno != GIST_ROOT_BLKNO)
296  flags = F_LEAF;
297  else
298  flags = 0;
299  GISTInitBuffer(buffer, flags);
300 
301  /* and fill it */
302  gistfillbuffer(page, tuples, num, FirstOffsetNumber);
303 
304  if (blkno == GIST_ROOT_BLKNO)
305  {
306  GistPageGetOpaque(page)->rightlink = InvalidBlockNumber;
307  GistPageSetNSN(page, xldata->orignsn);
308  GistClearFollowRight(page);
309  }
310  else
311  {
312  if (i < xldata->npage - 1)
313  {
314  BlockNumber nextblkno;
315 
316  XLogRecGetBlockTag(record, i + 2, NULL, NULL, &nextblkno);
317  GistPageGetOpaque(page)->rightlink = nextblkno;
318  }
319  else
320  GistPageGetOpaque(page)->rightlink = xldata->origrlink;
321  GistPageSetNSN(page, xldata->orignsn);
322  if (i < xldata->npage - 1 && !isrootsplit &&
323  xldata->markfollowright)
324  GistMarkFollowRight(page);
325  else
326  GistClearFollowRight(page);
327  }
328 
329  PageSetLSN(page, lsn);
330  MarkBufferDirty(buffer);
331 
332  if (i == 0)
333  firstbuffer = buffer;
334  else
335  UnlockReleaseBuffer(buffer);
336  }
337 
338  /* Fix follow-right data on left child page, if any */
339  if (XLogRecHasBlockRef(record, 0))
340  gistRedoClearFollowRight(record, 0);
341 
342  /* Finally, release lock on the first page */
343  UnlockReleaseBuffer(firstbuffer);
344 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1469
bool markfollowright
Definition: gistxlog.h:74
void gistfillbuffer(Page page, IndexTuple *itup, int len, OffsetNumber off)
Definition: gistutil.c:33
#define GistPageSetNSN(page, val)
Definition: gist.h:179
#define InvalidBuffer
Definition: buf.h:25
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:313
uint32 BlockNumber
Definition: block.h:31
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3534
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:305
#define FirstOffsetNumber
Definition: off.h:27
static IndexTuple * decodePageSplitRecord(char *begin, int len, int *n)
Definition: gistxlog.c:229
BlockNumber origrlink
Definition: gistxlog.h:69
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
GistNSN orignsn
Definition: gistxlog.h:70
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1498
#define GistClearFollowRight(page)
Definition: gist.h:176
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1522
#define GistPageGetOpaque(page)
Definition: gist.h:159
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:746
static void gistRedoClearFollowRight(XLogReaderState *record, uint8 block_id)
Definition: gistxlog.c:42
size_t Size
Definition: c.h:474
#define InvalidBlockNumber
Definition: block.h:33
#define GistMarkFollowRight(page)
Definition: gist.h:175
#define F_LEAF
Definition: gist.h:46
int i
#define GIST_ROOT_BLKNO
Definition: gist_private.h:262
void GISTInitBuffer(Buffer b, uint32 f)
Definition: gistutil.c:775
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78

◆ gistRedoPageUpdateRecord()

static void gistRedoPageUpdateRecord ( XLogReaderState record)
static

Definition at line 72 of file gistxlog.c.

References Assert, BLK_NEEDS_REDO, BufferGetPage, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, FirstOffsetNumber, GistMarkTuplesDeleted, GistPageIsLeaf, gistRedoClearFollowRight(), IndexTupleSize, InvalidOffsetNumber, MarkBufferDirty(), gistxlogPageUpdate::ntodelete, gistxlogPageUpdate::ntoinsert, OffsetNumberNext, GistSortedBuildPageState::page, PageAddItem, PageGetMaxOffsetNumber, PageIndexMultiDelete(), PageIndexTupleOverwrite(), PageIsEmpty, PageSetLSN, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by gist_redo().

73 {
74  XLogRecPtr lsn = record->EndRecPtr;
76  Buffer buffer;
77  Page page;
78 
79  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
80  {
81  char *begin;
82  char *data;
83  Size datalen;
84  int ninserted = 0;
85 
86  data = begin = XLogRecGetBlockData(record, 0, &datalen);
87 
88  page = (Page) BufferGetPage(buffer);
89 
90  if (xldata->ntodelete == 1 && xldata->ntoinsert == 1)
91  {
92  /*
93  * When replacing one tuple with one other tuple, we must use
94  * PageIndexTupleOverwrite for consistency with gistplacetopage.
95  */
96  OffsetNumber offnum = *((OffsetNumber *) data);
97  IndexTuple itup;
98  Size itupsize;
99 
100  data += sizeof(OffsetNumber);
101  itup = (IndexTuple) data;
102  itupsize = IndexTupleSize(itup);
103  if (!PageIndexTupleOverwrite(page, offnum, (Item) itup, itupsize))
104  elog(ERROR, "failed to add item to GiST index page, size %d bytes",
105  (int) itupsize);
106  data += itupsize;
107  /* should be nothing left after consuming 1 tuple */
108  Assert(data - begin == datalen);
109  /* update insertion count for assert check below */
110  ninserted++;
111  }
112  else if (xldata->ntodelete > 0)
113  {
114  /* Otherwise, delete old tuples if any */
115  OffsetNumber *todelete = (OffsetNumber *) data;
116 
117  data += sizeof(OffsetNumber) * xldata->ntodelete;
118 
119  PageIndexMultiDelete(page, todelete, xldata->ntodelete);
120  if (GistPageIsLeaf(page))
121  GistMarkTuplesDeleted(page);
122  }
123 
124  /* Add new tuples if any */
125  if (data - begin < datalen)
126  {
127  OffsetNumber off = (PageIsEmpty(page)) ? FirstOffsetNumber :
129 
130  while (data - begin < datalen)
131  {
132  IndexTuple itup = (IndexTuple) data;
133  Size sz = IndexTupleSize(itup);
134  OffsetNumber l;
135 
136  data += sz;
137 
138  l = PageAddItem(page, (Item) itup, sz, off, false, false);
139  if (l == InvalidOffsetNumber)
140  elog(ERROR, "failed to add item to GiST index page, size %d bytes",
141  (int) sz);
142  off++;
143  ninserted++;
144  }
145  }
146 
147  /* Check that XLOG record contained expected number of tuples */
148  Assert(ninserted == xldata->ntoinsert);
149 
150  PageSetLSN(page, lsn);
151  MarkBufferDirty(buffer);
152  }
153 
154  /*
155  * Fix follow-right data on left child page
156  *
157  * This must be done while still holding the lock on the target page. Note
158  * that even if the target page no longer exists, we still attempt to
159  * replay the change on the child page.
160  */
161  if (XLogRecHasBlockRef(record, 1))
162  gistRedoClearFollowRight(record, 1);
163 
164  if (BufferIsValid(buffer))
165  UnlockReleaseBuffer(buffer);
166 }
#define PageIsEmpty(page)
Definition: bufpage.h:222
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1469
#define GistMarkTuplesDeleted(page)
Definition: gist.h:167
Pointer Item
Definition: item.h:17
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:313
uint16 ntoinsert
Definition: gistxlog.h:40
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:410
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:357
uint16 ntodelete
Definition: gistxlog.h:39
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3534
#define ERROR
Definition: elog.h:43
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1280
#define FirstOffsetNumber
Definition: off.h:27
IndexTupleData * IndexTuple
Definition: itup.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define GistPageIsLeaf(page)
Definition: gist.h:161
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1522
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:293
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:746
static void gistRedoClearFollowRight(XLogReaderState *record, uint8 block_id)
Definition: gistxlog.c:42
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:1036
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
size_t Size
Definition: c.h:474
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define elog(elevel,...)
Definition: elog.h:214
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ gistXLogAssignLSN()

XLogRecPtr gistXLogAssignLSN ( void  )

Definition at line 601 of file gistxlog.c.

References XLOG_GIST_ASSIGN_LSN, XLOG_MARK_UNIMPORTANT, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLogSetRecordFlags().

Referenced by gistGetFakeLSN().

602 {
603  int dummy = 0;
604 
605  /*
606  * Records other than SWITCH_WAL must have content. We use an integer 0 to
607  * follow the restriction.
608  */
609  XLogBeginInsert();
611  XLogRegisterData((char *) &dummy, sizeof(dummy));
612  return XLogInsert(RM_GIST_ID, XLOG_GIST_ASSIGN_LSN);
613 }
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:404
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
#define XLOG_MARK_UNIMPORTANT
Definition: xlog.h:239
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define XLOG_GIST_ASSIGN_LSN
Definition: gistxlog.h:29

◆ gistXLogDelete()

XLogRecPtr gistXLogDelete ( Buffer  buffer,
OffsetNumber todelete,
int  ntodelete,
TransactionId  latestRemovedXid 
)

Definition at line 693 of file gistxlog.c.

References gistxlogDelete::latestRemovedXid, gistxlogDelete::ntodelete, REGBUF_STANDARD, SizeOfGistxlogDelete, XLOG_GIST_DELETE, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by gistprunepage().

695 {
696  gistxlogDelete xlrec;
697  XLogRecPtr recptr;
698 
699  xlrec.latestRemovedXid = latestRemovedXid;
700  xlrec.ntodelete = ntodelete;
701 
702  XLogBeginInsert();
703  XLogRegisterData((char *) &xlrec, SizeOfGistxlogDelete);
704 
705  /*
706  * We need the target-offsets array whether or not we store the whole
707  * buffer, to allow us to find the latestRemovedXid on a standby server.
708  */
709  XLogRegisterData((char *) todelete, ntodelete * sizeof(OffsetNumber));
710 
712 
713  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_DELETE);
714 
715  return recptr;
716 }
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:220
uint16 OffsetNumber
Definition: off.h:24
uint16 ntodelete
Definition: gistxlog.h:53
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define XLOG_GIST_DELETE
Definition: gistxlog.h:21
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define SizeOfGistxlogDelete
Definition: gistxlog.h:60
TransactionId latestRemovedXid
Definition: gistxlog.h:52
void XLogBeginInsert(void)
Definition: xloginsert.c:123

◆ gistXLogPageDelete()

XLogRecPtr gistXLogPageDelete ( Buffer  buffer,
FullTransactionId  xid,
Buffer  parentBuffer,
OffsetNumber  downlinkOffset 
)

Definition at line 577 of file gistxlog.c.

References gistxlogPageDelete::deleteXid, gistxlogPageDelete::downlinkOffset, REGBUF_STANDARD, SizeOfGistxlogPageDelete, XLOG_GIST_PAGE_DELETE, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by gistdeletepage().

579 {
580  gistxlogPageDelete xlrec;
581  XLogRecPtr recptr;
582 
583  xlrec.deleteXid = xid;
584  xlrec.downlinkOffset = downlinkOffset;
585 
586  XLogBeginInsert();
587  XLogRegisterData((char *) &xlrec, SizeOfGistxlogPageDelete);
588 
590  XLogRegisterBuffer(1, parentBuffer, REGBUF_STANDARD);
591 
592  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_DELETE);
593 
594  return recptr;
595 }
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:220
FullTransactionId deleteXid
Definition: gistxlog.h:87
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define SizeOfGistxlogPageDelete
Definition: gistxlog.h:92
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define XLOG_GIST_PAGE_DELETE
Definition: gistxlog.h:28
void XLogBeginInsert(void)
Definition: xloginsert.c:123
OffsetNumber downlinkOffset
Definition: gistxlog.h:88

◆ gistXLogPageReuse()

void gistXLogPageReuse ( Relation  rel,
BlockNumber  blkno,
FullTransactionId  latestRemovedXid 
)

Definition at line 619 of file gistxlog.c.

References gistxlogPageReuse::block, gistxlogPageReuse::latestRemovedFullXid, gistxlogPageReuse::node, RelationData::rd_node, SizeOfGistxlogPageReuse, XLOG_GIST_PAGE_REUSE, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by gistNewBuffer().

620 {
621  gistxlogPageReuse xlrec_reuse;
622 
623  /*
624  * Note that we don't register the buffer with the record, because this
625  * operation doesn't modify the page. This record only exists to provide a
626  * conflict point for Hot Standby.
627  */
628 
629  /* XLOG stuff */
630  xlrec_reuse.node = rel->rd_node;
631  xlrec_reuse.block = blkno;
632  xlrec_reuse.latestRemovedFullXid = latestRemovedXid;
633 
634  XLogBeginInsert();
635  XLogRegisterData((char *) &xlrec_reuse, SizeOfGistxlogPageReuse);
636 
637  XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_REUSE);
638 }
BlockNumber block
Definition: gistxlog.h:101
RelFileNode node
Definition: gistxlog.h:100
#define SizeOfGistxlogPageReuse
Definition: gistxlog.h:105
#define XLOG_GIST_PAGE_REUSE
Definition: gistxlog.h:23
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
RelFileNode rd_node
Definition: rel.h:55
void XLogBeginInsert(void)
Definition: xloginsert.c:123
FullTransactionId latestRemovedFullXid
Definition: gistxlog.h:102

◆ gistXLogSplit()

XLogRecPtr gistXLogSplit ( bool  page_is_leaf,
SplitedPageLayout dist,
BlockNumber  origrlink,
GistNSN  orignsn,
Buffer  leftchildbuf,
bool  markfollowright 
)

Definition at line 520 of file gistxlog.c.

References SplitedPageLayout::block, SplitedPageLayout::buffer, BufferIsValid, i, SplitedPageLayout::lenlist, SplitedPageLayout::list, gistxlogPageSplit::markfollowright, SplitedPageLayout::next, gistxlogPageSplit::npage, gistxlogPage::num, gistxlogPageSplit::origleaf, gistxlogPageSplit::orignsn, gistxlogPageSplit::origrlink, REGBUF_STANDARD, REGBUF_WILL_INIT, XLOG_GIST_PAGE_SPLIT, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by gistplacetopage().

524 {
525  gistxlogPageSplit xlrec;
526  SplitedPageLayout *ptr;
527  int npage = 0;
528  XLogRecPtr recptr;
529  int i;
530 
531  for (ptr = dist; ptr; ptr = ptr->next)
532  npage++;
533 
534  xlrec.origrlink = origrlink;
535  xlrec.orignsn = orignsn;
536  xlrec.origleaf = page_is_leaf;
537  xlrec.npage = (uint16) npage;
538  xlrec.markfollowright = markfollowright;
539 
540  XLogBeginInsert();
541 
542  /*
543  * Include a full page image of the child buf. (only necessary if a
544  * checkpoint happened since the child page was split)
545  */
546  if (BufferIsValid(leftchildbuf))
547  XLogRegisterBuffer(0, leftchildbuf, REGBUF_STANDARD);
548 
549  /*
550  * NOTE: We register a lot of data. The caller must've called
551  * XLogEnsureRecordSpace() to prepare for that. We cannot do it here,
552  * because we're already in a critical section. If you change the number
553  * of buffer or data registrations here, make sure you modify the
554  * XLogEnsureRecordSpace() calls accordingly!
555  */
556  XLogRegisterData((char *) &xlrec, sizeof(gistxlogPageSplit));
557 
558  i = 1;
559  for (ptr = dist; ptr; ptr = ptr->next)
560  {
562  XLogRegisterBufData(i, (char *) &(ptr->block.num), sizeof(int));
563  XLogRegisterBufData(i, (char *) ptr->list, ptr->lenlist);
564  i++;
565  }
566 
567  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT);
568 
569  return recptr;
570 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:368
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:220
bool markfollowright
Definition: gistxlog.h:74
#define REGBUF_WILL_INIT
Definition: xloginsert.h:33
IndexTupleData * list
Definition: gist_private.h:194
gistxlogPage block
Definition: gist_private.h:193
unsigned short uint16
Definition: c.h:374
#define XLOG_GIST_PAGE_SPLIT
Definition: gistxlog.h:25
#define REGBUF_STANDARD
Definition: xloginsert.h:35
BlockNumber origrlink
Definition: gistxlog.h:69
struct SplitedPageLayout * next
Definition: gist_private.h:200
GistNSN orignsn
Definition: gistxlog.h:70
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
int i
void XLogBeginInsert(void)
Definition: xloginsert.c:123

◆ gistXLogUpdate()

XLogRecPtr gistXLogUpdate ( Buffer  buffer,
OffsetNumber todelete,
int  ntodelete,
IndexTuple itup,
int  ituplen,
Buffer  leftchildbuf 
)

Definition at line 652 of file gistxlog.c.

References BufferIsValid, i, IndexTupleSize, gistxlogPageUpdate::ntodelete, gistxlogPageUpdate::ntoinsert, REGBUF_STANDARD, XLOG_GIST_PAGE_UPDATE, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by gistplacetopage(), and gistvacuumpage().

656 {
657  gistxlogPageUpdate xlrec;
658  int i;
659  XLogRecPtr recptr;
660 
661  xlrec.ntodelete = ntodelete;
662  xlrec.ntoinsert = ituplen;
663 
664  XLogBeginInsert();
665  XLogRegisterData((char *) &xlrec, sizeof(gistxlogPageUpdate));
666 
668  XLogRegisterBufData(0, (char *) todelete, sizeof(OffsetNumber) * ntodelete);
669 
670  /* new tuples */
671  for (i = 0; i < ituplen; i++)
672  XLogRegisterBufData(0, (char *) (itup[i]), IndexTupleSize(itup[i]));
673 
674  /*
675  * Include a full page image of the child buf. (only necessary if a
676  * checkpoint happened since the child page was split)
677  */
678  if (BufferIsValid(leftchildbuf))
679  XLogRegisterBuffer(1, leftchildbuf, REGBUF_STANDARD);
680 
681  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_UPDATE);
682 
683  return recptr;
684 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:368
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:220
uint16 ntoinsert
Definition: gistxlog.h:40
uint16 ntodelete
Definition: gistxlog.h:39
uint16 OffsetNumber
Definition: off.h:24
#define REGBUF_STANDARD
Definition: xloginsert.h:35
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:330
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
int i
#define XLOG_GIST_PAGE_UPDATE
Definition: gistxlog.h:20
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define IndexTupleSize(itup)
Definition: itup.h:71

Variable Documentation

◆ opCtx

MemoryContext opCtx
static

Definition at line 28 of file gistxlog.c.