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:804
void * palloc(Size size)
Definition: mcxt.c:1062
int i
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ gist_mask()

void gist_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 458 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.

459 {
460  Page page = (Page) pagedata;
461 
463 
464  mask_page_hint_bits(page);
465  mask_unused_space(page);
466 
467  /*
468  * NSN is nothing but a special purpose LSN. Hence, mask it for the same
469  * reason as mask_page_lsn_and_checksum.
470  */
471  GistPageSetNSN(page, (uint64) MASK_MARKER);
472 
473  /*
474  * We update F_FOLLOW_RIGHT flag on the left child after writing WAL
475  * record. Hence, mask this flag. See gistplacetopage() for details.
476  */
477  GistMarkFollowRight(page);
478 
479  if (GistPageIsLeaf(page))
480  {
481  /*
482  * In gist leaf pages, it is possible to modify the LP_FLAGS without
483  * emitting any WAL record. Hence, mask the line pointer flags. See
484  * gistkillitems() for details.
485  */
486  mask_lp_flags(page);
487  }
488 
489  /*
490  * During gist redo, we never mark a page as garbage. Hence, mask it to
491  * ignore any differences.
492  */
494 }
#define GistClearPageHasGarbage(page)
Definition: gist.h:180
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
#define GistPageSetNSN(page, val)
Definition: gist.h:187
void mask_unused_space(Page page)
Definition: bufmask.c:71
#define MASK_MARKER
Definition: bufmask.h:24
#define GistPageIsLeaf(page)
Definition: gist.h:169
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
#define GistMarkFollowRight(page)
Definition: gist.h:183
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 402 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.

403 {
404  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
405  MemoryContext oldCxt;
406 
407  /*
408  * GiST indexes do not require any conflict processing. NB: If we ever
409  * implement a similar optimization we have in b-tree, and remove killed
410  * tuples outside VACUUM, we'll need to handle that here.
411  */
412 
413  oldCxt = MemoryContextSwitchTo(opCtx);
414  switch (info)
415  {
417  gistRedoPageUpdateRecord(record);
418  break;
419  case XLOG_GIST_DELETE:
420  gistRedoDeleteRecord(record);
421  break;
423  gistRedoPageReuse(record);
424  break;
426  gistRedoPageSplitRecord(record);
427  break;
429  gistRedoPageDelete(record);
430  break;
432  /* nop. See gistGetFakeLSN(). */
433  break;
434  default:
435  elog(PANIC, "gist_redo: unknown op code %u", info);
436  }
437 
438  MemoryContextSwitchTo(oldCxt);
440 }
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:439
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
#define PANIC
Definition: elog.h:50
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:315
#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:232
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 449 of file gistxlog.c.

References MemoryContextDelete().

450 {
452 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static MemoryContext opCtx
Definition: gistxlog.c:28

◆ gist_xlog_startup()

void gist_xlog_startup ( void  )

Definition at line 443 of file gistxlog.c.

References createTempGistContext().

444 {
446 }
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:1565
#define GistPageSetNSN(page, val)
Definition: gist.h:187
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3791
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define GistClearFollowRight(page)
Definition: gist.h:184
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:312
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRedoAction
Definition: xlogutils.h:69
#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_PRUNE records provide the highest xid cleaned by
188  * the vacuum of the heap and so we can resolve any conflicts just once
189  * when that arrives. After that we know that no conflicts exist from
190  * 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:180
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1565
#define GistMarkTuplesDeleted(page)
Definition: gist.h:175
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3791
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:321
uint16 ntodelete
Definition: gistxlog.h:53
#define InHotStandby
Definition: xlogutils.h:57
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1531
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:312
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:1154
#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:443
#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:1045
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1565
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
FullTransactionId deleteXid
Definition: gistxlog.h:87
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3791
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
static void GistPageSetDeleted(Page page, FullTransactionId deletexid)
Definition: gist.h:204
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:312
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, gistxlogPageReuse::node, ResolveRecoveryConflictWithSnapshotFullXid(), 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  * GlobalVisCheckRemovableFullXid(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)
398  xlrec->node);
399 }
RelFileNode node
Definition: gistxlog.h:100
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
void ResolveRecoveryConflictWithSnapshotFullXid(FullTransactionId latestRemovedFullXid, RelFileNode node)
Definition: standby.c:475
#define InHotStandby
Definition: xlogutils.h:57
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:1565
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:187
#define InvalidBuffer
Definition: buf.h:25
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:323
uint32 BlockNumber
Definition: block.h:31
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
#define XLogRecGetData(decoder)
Definition: xlogreader.h:320
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3791
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:324
#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:1531
#define GistClearFollowRight(page)
Definition: gist.h:184
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1555
#define GistPageGetOpaque(page)
Definition: gist.h:167
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
static void gistRedoClearFollowRight(XLogReaderState *record, uint8 block_id)
Definition: gistxlog.c:42
size_t Size
Definition: c.h:540
#define InvalidBlockNumber
Definition: block.h:33
#define GistMarkFollowRight(page)
Definition: gist.h:183
#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:772
#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:1565
#define GistMarkTuplesDeleted(page)
Definition: gist.h:175
Pointer Item
Definition: item.h:17
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:323
uint16 ntoinsert
Definition: gistxlog.h:40
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
#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:320
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3791
#define ERROR
Definition: elog.h:46
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1398
#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:169
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1555
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:312
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
static void gistRedoClearFollowRight(XLogReaderState *record, uint8 block_id)
Definition: gistxlog.c:42
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:1154
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
size_t Size
Definition: c.h:540
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define elog(elevel,...)
Definition: elog.h:232
#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 581 of file gistxlog.c.

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

Referenced by gistGetFakeLSN().

582 {
583  int dummy = 0;
584 
585  /*
586  * Records other than SWITCH_WAL must have content. We use an integer 0 to
587  * follow the restriction.
588  */
589  XLogBeginInsert();
591  XLogRegisterData((char *) &dummy, sizeof(dummy));
592  return XLogInsert(RM_GIST_ID, XLOG_GIST_ASSIGN_LSN);
593 }
void XLogSetRecordFlags(uint8 flags)
Definition: xloginsert.c:416
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
#define XLOG_MARK_UNIMPORTANT
Definition: xlog.h:214
void XLogBeginInsert(void)
Definition: xloginsert.c:135
#define XLOG_GIST_ASSIGN_LSN
Definition: gistxlog.h:29

◆ gistXLogDelete()

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

Definition at line 673 of file gistxlog.c.

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

Referenced by gistprunepage().

675 {
676  gistxlogDelete xlrec;
677  XLogRecPtr recptr;
678 
679  xlrec.latestRemovedXid = latestRemovedXid;
680  xlrec.ntodelete = ntodelete;
681 
682  XLogBeginInsert();
683  XLogRegisterData((char *) &xlrec, SizeOfGistxlogDelete);
684 
685  /*
686  * We need the target-offsets array whether or not we store the whole
687  * buffer, to allow us to find the latestRemovedXid on a standby server.
688  */
689  XLogRegisterData((char *) todelete, ntodelete * sizeof(OffsetNumber));
690 
692 
693  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_DELETE);
694 
695  return recptr;
696 }
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:232
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:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define SizeOfGistxlogDelete
Definition: gistxlog.h:60
TransactionId latestRemovedXid
Definition: gistxlog.h:52
void XLogBeginInsert(void)
Definition: xloginsert.c:135

◆ gistXLogPageDelete()

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

Definition at line 557 of file gistxlog.c.

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

Referenced by gistdeletepage().

559 {
560  gistxlogPageDelete xlrec;
561  XLogRecPtr recptr;
562 
563  xlrec.deleteXid = xid;
564  xlrec.downlinkOffset = downlinkOffset;
565 
566  XLogBeginInsert();
567  XLogRegisterData((char *) &xlrec, SizeOfGistxlogPageDelete);
568 
570  XLogRegisterBuffer(1, parentBuffer, REGBUF_STANDARD);
571 
572  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_DELETE);
573 
574  return recptr;
575 }
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:232
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:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define XLOG_GIST_PAGE_DELETE
Definition: gistxlog.h:28
void XLogBeginInsert(void)
Definition: xloginsert.c:135
OffsetNumber downlinkOffset
Definition: gistxlog.h:88

◆ gistXLogPageReuse()

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

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

600 {
601  gistxlogPageReuse xlrec_reuse;
602 
603  /*
604  * Note that we don't register the buffer with the record, because this
605  * operation doesn't modify the page. This record only exists to provide a
606  * conflict point for Hot Standby.
607  */
608 
609  /* XLOG stuff */
610  xlrec_reuse.node = rel->rd_node;
611  xlrec_reuse.block = blkno;
612  xlrec_reuse.latestRemovedFullXid = latestRemovedXid;
613 
614  XLogBeginInsert();
615  XLogRegisterData((char *) &xlrec_reuse, SizeOfGistxlogPageReuse);
616 
617  XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_REUSE);
618 }
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:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
RelFileNode rd_node
Definition: rel.h:56
void XLogBeginInsert(void)
Definition: xloginsert.c:135
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 500 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().

504 {
505  gistxlogPageSplit xlrec;
506  SplitedPageLayout *ptr;
507  int npage = 0;
508  XLogRecPtr recptr;
509  int i;
510 
511  for (ptr = dist; ptr; ptr = ptr->next)
512  npage++;
513 
514  xlrec.origrlink = origrlink;
515  xlrec.orignsn = orignsn;
516  xlrec.origleaf = page_is_leaf;
517  xlrec.npage = (uint16) npage;
518  xlrec.markfollowright = markfollowright;
519 
520  XLogBeginInsert();
521 
522  /*
523  * Include a full page image of the child buf. (only necessary if a
524  * checkpoint happened since the child page was split)
525  */
526  if (BufferIsValid(leftchildbuf))
527  XLogRegisterBuffer(0, leftchildbuf, REGBUF_STANDARD);
528 
529  /*
530  * NOTE: We register a lot of data. The caller must've called
531  * XLogEnsureRecordSpace() to prepare for that. We cannot do it here,
532  * because we're already in a critical section. If you change the number
533  * of buffer or data registrations here, make sure you modify the
534  * XLogEnsureRecordSpace() calls accordingly!
535  */
536  XLogRegisterData((char *) &xlrec, sizeof(gistxlogPageSplit));
537 
538  i = 1;
539  for (ptr = dist; ptr; ptr = ptr->next)
540  {
542  XLogRegisterBufData(i, (char *) &(ptr->block.num), sizeof(int));
543  XLogRegisterBufData(i, (char *) ptr->list, ptr->lenlist);
544  i++;
545  }
546 
547  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT);
548 
549  return recptr;
550 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:378
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:232
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:440
#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:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
int i
void XLogBeginInsert(void)
Definition: xloginsert.c:135

◆ gistXLogUpdate()

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

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

636 {
637  gistxlogPageUpdate xlrec;
638  int i;
639  XLogRecPtr recptr;
640 
641  xlrec.ntodelete = ntodelete;
642  xlrec.ntoinsert = ituplen;
643 
644  XLogBeginInsert();
645  XLogRegisterData((char *) &xlrec, sizeof(gistxlogPageUpdate));
646 
648  XLogRegisterBufData(0, (char *) todelete, sizeof(OffsetNumber) * ntodelete);
649 
650  /* new tuples */
651  for (i = 0; i < ituplen; i++)
652  XLogRegisterBufData(0, (char *) (itup[i]), IndexTupleSize(itup[i]));
653 
654  /*
655  * Include a full page image of the child buf. (only necessary if a
656  * checkpoint happened since the child page was split)
657  */
658  if (BufferIsValid(leftchildbuf))
659  XLogRegisterBuffer(1, leftchildbuf, REGBUF_STANDARD);
660 
661  recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_UPDATE);
662 
663  return recptr;
664 }
void XLogRegisterBufData(uint8 block_id, char *data, int len)
Definition: xloginsert.c:378
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:232
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:340
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:434
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:135
#define IndexTupleSize(itup)
Definition: itup.h:71

Variable Documentation

◆ opCtx

MemoryContext opCtx
static

Definition at line 28 of file gistxlog.c.