PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
spgxlog.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/spgist_private.h"
#include "access/spgxlog.h"
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xlogutils.h"
#include "storage/standby.h"
#include "utils/memutils.h"
Include dependency graph for spgxlog.c:

Go to the source code of this file.

Functions

static void fillFakeState (SpGistState *state, spgxlogState stateSrc)
 
static void addOrReplaceTuple (Page page, Item tuple, int size, OffsetNumber offset)
 
static void spgRedoCreateIndex (XLogReaderState *record)
 
static void spgRedoAddLeaf (XLogReaderState *record)
 
static void spgRedoMoveLeafs (XLogReaderState *record)
 
static void spgRedoAddNode (XLogReaderState *record)
 
static void spgRedoSplitTuple (XLogReaderState *record)
 
static void spgRedoPickSplit (XLogReaderState *record)
 
static void spgRedoVacuumLeaf (XLogReaderState *record)
 
static void spgRedoVacuumRoot (XLogReaderState *record)
 
static void spgRedoVacuumRedirect (XLogReaderState *record)
 
void spg_redo (XLogReaderState *record)
 
void spg_xlog_startup (void)
 
void spg_xlog_cleanup (void)
 
void spg_mask (char *pagedata, BlockNumber blkno)
 

Variables

static MemoryContext opCtx
 

Function Documentation

static void addOrReplaceTuple ( Page  page,
Item  tuple,
int  size,
OffsetNumber  offset 
)
static

Definition at line 52 of file spgxlog.c.

References Assert, elog, ERROR, PageAddItem, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageIndexTupleDelete(), SPGIST_PLACEHOLDER, SpGistPageGetOpaque, and SpGistDeadTupleData::tupstate.

Referenced by spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), and spgRedoSplitTuple().

53 {
54  if (offset <= PageGetMaxOffsetNumber(page))
55  {
57  PageGetItemId(page, offset));
58 
59  if (dt->tupstate != SPGIST_PLACEHOLDER)
60  elog(ERROR, "SPGiST tuple to be replaced is not a placeholder");
61 
62  Assert(SpGistPageGetOpaque(page)->nPlaceholder > 0);
63  SpGistPageGetOpaque(page)->nPlaceholder--;
64 
65  PageIndexTupleDelete(page, offset);
66  }
67 
68  Assert(offset <= PageGetMaxOffsetNumber(page) + 1);
69 
70  if (PageAddItem(page, tuple, size, offset, false, false) != offset)
71  elog(ERROR, "failed to add item of size %u to SPGiST index page",
72  size);
73 }
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:727
#define SPGIST_PLACEHOLDER
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
#define ERROR
Definition: elog.h:43
SpGistDeadTupleData * SpGistDeadTuple
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
unsigned int tupstate
#define Assert(condition)
Definition: c.h:675
#define SpGistPageGetOpaque(page)
#define elog
Definition: elog.h:219
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
static void fillFakeState ( SpGistState state,
spgxlogState  stateSrc 
)
static

Definition at line 37 of file spgxlog.c.

References SpGistState::deadTupleStorage, spgxlogState::isBuild, SpGistState::isBuild, spgxlogState::myXid, SpGistState::myXid, palloc0(), and SGDTSIZE.

Referenced by spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), and spgRedoVacuumLeaf().

38 {
39  memset(state, 0, sizeof(*state));
40 
41  state->myXid = stateSrc.myXid;
42  state->isBuild = stateSrc.isBuild;
44 }
#define SGDTSIZE
TransactionId myXid
void * palloc0(Size size)
Definition: mcxt.c:878
char * deadTupleStorage
bool isBuild
Definition: spgxlog.h:39
TransactionId myXid
Definition: spgxlog.h:38
void spg_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 1033 of file spgxlog.c.

References mask_page_hint_bits(), mask_page_lsn(), mask_unused_space(), and SpGistPageIsMeta.

1034 {
1035  Page page = (Page) pagedata;
1036 
1037  mask_page_lsn(page);
1038 
1039  mask_page_hint_bits(page);
1040 
1041  /*
1042  * Any SpGist page other than meta contains unused space which needs to be
1043  * masked.
1044  */
1045  if (!SpGistPageIsMeta(page))
1046  mask_unused_space(page);
1047 }
void mask_page_hint_bits(Page page)
Definition: bufmask.c:44
void mask_unused_space(Page page)
Definition: bufmask.c:69
void mask_page_lsn(Page page)
Definition: bufmask.c:30
#define SpGistPageIsMeta(page)
Pointer Page
Definition: bufpage.h:74
void spg_redo ( XLogReaderState record)

Definition at line 971 of file spgxlog.c.

References elog, MemoryContextReset(), MemoryContextSwitchTo(), PANIC, spgRedoAddLeaf(), spgRedoAddNode(), spgRedoCreateIndex(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), XLOG_SPGIST_ADD_LEAF, XLOG_SPGIST_ADD_NODE, XLOG_SPGIST_CREATE_INDEX, XLOG_SPGIST_MOVE_LEAFS, XLOG_SPGIST_PICKSPLIT, XLOG_SPGIST_SPLIT_TUPLE, XLOG_SPGIST_VACUUM_LEAF, XLOG_SPGIST_VACUUM_REDIRECT, XLOG_SPGIST_VACUUM_ROOT, XLogRecGetInfo, and XLR_INFO_MASK.

972 {
973  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
974  MemoryContext oldCxt;
975 
976  oldCxt = MemoryContextSwitchTo(opCtx);
977  switch (info)
978  {
980  spgRedoCreateIndex(record);
981  break;
983  spgRedoAddLeaf(record);
984  break;
986  spgRedoMoveLeafs(record);
987  break;
989  spgRedoAddNode(record);
990  break;
992  spgRedoSplitTuple(record);
993  break;
995  spgRedoPickSplit(record);
996  break;
998  spgRedoVacuumLeaf(record);
999  break;
1001  spgRedoVacuumRoot(record);
1002  break;
1004  spgRedoVacuumRedirect(record);
1005  break;
1006  default:
1007  elog(PANIC, "spg_redo: unknown op code %u", info);
1008  }
1009 
1010  MemoryContextSwitchTo(oldCxt);
1012 }
#define XLOG_SPGIST_MOVE_LEAFS
Definition: spgxlog.h:23
static void spgRedoVacuumRedirect(XLogReaderState *record)
Definition: spgxlog.c:894
#define XLOG_SPGIST_VACUUM_REDIRECT
Definition: spgxlog.h:29
static MemoryContext opCtx
Definition: spgxlog.c:27
#define XLOG_SPGIST_SPLIT_TUPLE
Definition: spgxlog.h:25
static void spgRedoAddNode(XLogReaderState *record)
Definition: spgxlog.c:318
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned char uint8
Definition: c.h:266
static void spgRedoSplitTuple(XLogReaderState *record)
Definition: spgxlog.c:485
#define XLOG_SPGIST_ADD_NODE
Definition: spgxlog.h:24
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
#define XLOG_SPGIST_ADD_LEAF
Definition: spgxlog.h:22
#define PANIC
Definition: elog.h:53
#define XLOG_SPGIST_PICKSPLIT
Definition: spgxlog.h:26
#define XLOG_SPGIST_VACUUM_ROOT
Definition: spgxlog.h:28
static void spgRedoAddLeaf(XLogReaderState *record)
Definition: spgxlog.c:108
#define XLOG_SPGIST_CREATE_INDEX
Definition: spgxlog.h:21
static void spgRedoVacuumLeaf(XLogReaderState *record)
Definition: spgxlog.c:785
static void spgRedoPickSplit(XLogReaderState *record)
Definition: spgxlog.c:563
static void spgRedoCreateIndex(XLogReaderState *record)
Definition: spgxlog.c:76
static void spgRedoVacuumRoot(XLogReaderState *record)
Definition: spgxlog.c:868
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:216
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define XLOG_SPGIST_VACUUM_LEAF
Definition: spgxlog.h:27
#define elog
Definition: elog.h:219
static void spgRedoMoveLeafs(XLogReaderState *record)
Definition: spgxlog.c:205
void spg_xlog_cleanup ( void  )

Definition at line 1023 of file spgxlog.c.

References MemoryContextDelete(), and NULL.

1024 {
1026  opCtx = NULL;
1027 }
static MemoryContext opCtx
Definition: spgxlog.c:27
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
#define NULL
Definition: c.h:229
void spg_xlog_startup ( void  )

Definition at line 1015 of file spgxlog.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), and CurrentMemoryContext.

1016 {
1018  "SP-GiST temporary context",
1020 }
static MemoryContext opCtx
Definition: spgxlog.c:27
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
static void spgRedoAddLeaf ( XLogReaderState record)
static

Definition at line 108 of file spgxlog.c.

References addOrReplaceTuple(), Assert, BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, InvalidOffsetNumber, MarkBufferDirty(), spgxlogAddLeaf::newPage, SpGistLeafTupleData::nextOffset, spgxlogAddLeaf::nodeI, NULL, spgxlogAddLeaf::offnumHeadLeaf, spgxlogAddLeaf::offnumLeaf, spgxlogAddLeaf::offnumParent, PageAddItem, PageGetItem, PageGetItemId, PageIndexTupleDelete(), PageSetLSN, SpGistLeafTupleData::size, SPGIST_LEAF, SPGIST_NULLS, SpGistInitBuffer(), spgUpdateNodeLink(), spgxlogAddLeaf::storesNulls, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockTag(), and XLogRecGetData.

Referenced by spg_redo().

109 {
110  XLogRecPtr lsn = record->EndRecPtr;
111  char *ptr = XLogRecGetData(record);
112  spgxlogAddLeaf *xldata = (spgxlogAddLeaf *) ptr;
113  char *leafTuple;
114  SpGistLeafTupleData leafTupleHdr;
115  Buffer buffer;
116  Page page;
117  XLogRedoAction action;
118 
119  ptr += sizeof(spgxlogAddLeaf);
120  leafTuple = ptr;
121  /* the leaf tuple is unaligned, so make a copy to access its header */
122  memcpy(&leafTupleHdr, leafTuple, sizeof(SpGistLeafTupleData));
123 
124  /*
125  * In normal operation we would have both current and parent pages locked
126  * simultaneously; but in WAL replay it should be safe to update the leaf
127  * page before updating the parent.
128  */
129  if (xldata->newPage)
130  {
131  buffer = XLogInitBufferForRedo(record, 0);
132  SpGistInitBuffer(buffer,
133  SPGIST_LEAF | (xldata->storesNulls ? SPGIST_NULLS : 0));
134  action = BLK_NEEDS_REDO;
135  }
136  else
137  action = XLogReadBufferForRedo(record, 0, &buffer);
138 
139  if (action == BLK_NEEDS_REDO)
140  {
141  page = BufferGetPage(buffer);
142 
143  /* insert new tuple */
144  if (xldata->offnumLeaf != xldata->offnumHeadLeaf)
145  {
146  /* normal cases, tuple was added by SpGistPageAddNewItem */
147  addOrReplaceTuple(page, (Item) leafTuple, leafTupleHdr.size,
148  xldata->offnumLeaf);
149 
150  /* update head tuple's chain link if needed */
151  if (xldata->offnumHeadLeaf != InvalidOffsetNumber)
152  {
153  SpGistLeafTuple head;
154 
155  head = (SpGistLeafTuple) PageGetItem(page,
156  PageGetItemId(page, xldata->offnumHeadLeaf));
157  Assert(head->nextOffset == leafTupleHdr.nextOffset);
158  head->nextOffset = xldata->offnumLeaf;
159  }
160  }
161  else
162  {
163  /* replacing a DEAD tuple */
164  PageIndexTupleDelete(page, xldata->offnumLeaf);
165  if (PageAddItem(page,
166  (Item) leafTuple, leafTupleHdr.size,
167  xldata->offnumLeaf, false, false) != xldata->offnumLeaf)
168  elog(ERROR, "failed to add item of size %u to SPGiST index page",
169  leafTupleHdr.size);
170  }
171 
172  PageSetLSN(page, lsn);
173  MarkBufferDirty(buffer);
174  }
175  if (BufferIsValid(buffer))
176  UnlockReleaseBuffer(buffer);
177 
178  /* update parent downlink if necessary */
179  if (xldata->offnumParent != InvalidOffsetNumber)
180  {
181  if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
182  {
183  SpGistInnerTuple tuple;
184  BlockNumber blknoLeaf;
185 
186  XLogRecGetBlockTag(record, 0, NULL, NULL, &blknoLeaf);
187 
188  page = BufferGetPage(buffer);
189 
190  tuple = (SpGistInnerTuple) PageGetItem(page,
191  PageGetItemId(page, xldata->offnumParent));
192 
193  spgUpdateNodeLink(tuple, xldata->nodeI,
194  blknoLeaf, xldata->offnumLeaf);
195 
196  PageSetLSN(page, lsn);
197  MarkBufferDirty(buffer);
198  }
199  if (BufferIsValid(buffer))
200  UnlockReleaseBuffer(buffer);
201  }
202 }
void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN, BlockNumber blkno, OffsetNumber offset)
Definition: spgdoinsert.c:50
OffsetNumber offnumParent
Definition: spgxlog.h:53
SpGistInnerTupleData * SpGistInnerTuple
struct spgxlogAddLeaf spgxlogAddLeaf
OffsetNumber offnumLeaf
Definition: spgxlog.h:50
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:727
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
#define SPGIST_NULLS
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
uint32 BlockNumber
Definition: block.h:31
static void addOrReplaceTuple(Page page, Item tuple, int size, OffsetNumber offset)
Definition: spgxlog.c:52
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
bool newPage
Definition: spgxlog.h:48
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1307
OffsetNumber offnumHeadLeaf
Definition: spgxlog.h:51
bool storesNulls
Definition: spgxlog.h:49
#define InvalidOffsetNumber
Definition: off.h:26
uint16 nodeI
Definition: spgxlog.h:54
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
XLogRedoAction
Definition: xlogutils.h:27
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
OffsetNumber nextOffset
#define elog
Definition: elog.h:219
SpGistLeafTupleData * SpGistLeafTuple
#define SPGIST_LEAF
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
static void spgRedoAddNode ( XLogReaderState record)
static

Definition at line 318 of file spgxlog.c.

References addOrReplaceTuple(), Assert, BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, fillFakeState(), InvalidBlockNumber, InvalidOffsetNumber, SpGistState::isBuild, MarkBufferDirty(), spgxlogAddNode::newPage, spgxlogAddNode::nodeI, NULL, spgxlogAddNode::offnum, spgxlogAddNode::offnumNew, spgxlogAddNode::offnumParent, PageAddItem, PageGetItem, PageGetItemId, PageIndexTupleDelete(), PageSetLSN, spgxlogAddNode::parentBlk, SpGistInnerTupleData::size, SpGistDeadTupleData::size, spgFormDeadTuple(), SPGIST_PLACEHOLDER, SPGIST_REDIRECT, SpGistInitBuffer(), SpGistPageGetOpaque, spgUpdateNodeLink(), spgxlogAddNode::stateSrc, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockTag(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by spg_redo().

319 {
320  XLogRecPtr lsn = record->EndRecPtr;
321  char *ptr = XLogRecGetData(record);
322  spgxlogAddNode *xldata = (spgxlogAddNode *) ptr;
323  char *innerTuple;
324  SpGistInnerTupleData innerTupleHdr;
326  Buffer buffer;
327  Page page;
328  XLogRedoAction action;
329 
330  ptr += sizeof(spgxlogAddNode);
331  innerTuple = ptr;
332  /* the tuple is unaligned, so make a copy to access its header */
333  memcpy(&innerTupleHdr, innerTuple, sizeof(SpGistInnerTupleData));
334 
335  fillFakeState(&state, xldata->stateSrc);
336 
337  if (!XLogRecHasBlockRef(record, 1))
338  {
339  /* update in place */
340  Assert(xldata->parentBlk == -1);
341  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
342  {
343  page = BufferGetPage(buffer);
344 
345  PageIndexTupleDelete(page, xldata->offnum);
346  if (PageAddItem(page, (Item) innerTuple, innerTupleHdr.size,
347  xldata->offnum,
348  false, false) != xldata->offnum)
349  elog(ERROR, "failed to add item of size %u to SPGiST index page",
350  innerTupleHdr.size);
351 
352  PageSetLSN(page, lsn);
353  MarkBufferDirty(buffer);
354  }
355  if (BufferIsValid(buffer))
356  UnlockReleaseBuffer(buffer);
357  }
358  else
359  {
360  BlockNumber blkno;
361  BlockNumber blknoNew;
362 
363  XLogRecGetBlockTag(record, 0, NULL, NULL, &blkno);
364  XLogRecGetBlockTag(record, 1, NULL, NULL, &blknoNew);
365 
366  /*
367  * In normal operation we would have all three pages (source, dest,
368  * and parent) locked simultaneously; but in WAL replay it should be
369  * safe to update them one at a time, as long as we do it in the right
370  * order. We must insert the new tuple before replacing the old tuple
371  * with the redirect tuple.
372  */
373 
374  /* Install new tuple first so redirect is valid */
375  if (xldata->newPage)
376  {
377  /* AddNode is not used for nulls pages */
378  buffer = XLogInitBufferForRedo(record, 1);
379  SpGistInitBuffer(buffer, 0);
380  action = BLK_NEEDS_REDO;
381  }
382  else
383  action = XLogReadBufferForRedo(record, 1, &buffer);
384  if (action == BLK_NEEDS_REDO)
385  {
386  page = BufferGetPage(buffer);
387 
388  addOrReplaceTuple(page, (Item) innerTuple,
389  innerTupleHdr.size, xldata->offnumNew);
390 
391  /*
392  * If parent is in this same page, update it now.
393  */
394  if (xldata->parentBlk == 1)
395  {
396  SpGistInnerTuple parentTuple;
397 
398  parentTuple = (SpGistInnerTuple) PageGetItem(page,
399  PageGetItemId(page, xldata->offnumParent));
400 
401  spgUpdateNodeLink(parentTuple, xldata->nodeI,
402  blknoNew, xldata->offnumNew);
403  }
404  PageSetLSN(page, lsn);
405  MarkBufferDirty(buffer);
406  }
407  if (BufferIsValid(buffer))
408  UnlockReleaseBuffer(buffer);
409 
410  /* Delete old tuple, replacing it with redirect or placeholder tuple */
411  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
412  {
413  SpGistDeadTuple dt;
414 
415  page = BufferGetPage(buffer);
416 
417  if (state.isBuild)
421  else
422  dt = spgFormDeadTuple(&state, SPGIST_REDIRECT,
423  blknoNew,
424  xldata->offnumNew);
425 
426  PageIndexTupleDelete(page, xldata->offnum);
427  if (PageAddItem(page, (Item) dt, dt->size,
428  xldata->offnum,
429  false, false) != xldata->offnum)
430  elog(ERROR, "failed to add item of size %u to SPGiST index page",
431  dt->size);
432 
433  if (state.isBuild)
434  SpGistPageGetOpaque(page)->nPlaceholder++;
435  else
436  SpGistPageGetOpaque(page)->nRedirection++;
437 
438  /*
439  * If parent is in this same page, update it now.
440  */
441  if (xldata->parentBlk == 0)
442  {
443  SpGistInnerTuple parentTuple;
444 
445  parentTuple = (SpGistInnerTuple) PageGetItem(page,
446  PageGetItemId(page, xldata->offnumParent));
447 
448  spgUpdateNodeLink(parentTuple, xldata->nodeI,
449  blknoNew, xldata->offnumNew);
450  }
451  PageSetLSN(page, lsn);
452  MarkBufferDirty(buffer);
453  }
454  if (BufferIsValid(buffer))
455  UnlockReleaseBuffer(buffer);
456 
457  /*
458  * Update parent downlink (if we didn't do it as part of the source or
459  * destination page update already).
460  */
461  if (xldata->parentBlk == 2)
462  {
463  if (XLogReadBufferForRedo(record, 2, &buffer) == BLK_NEEDS_REDO)
464  {
465  SpGistInnerTuple parentTuple;
466 
467  page = BufferGetPage(buffer);
468 
469  parentTuple = (SpGistInnerTuple) PageGetItem(page,
470  PageGetItemId(page, xldata->offnumParent));
471 
472  spgUpdateNodeLink(parentTuple, xldata->nodeI,
473  blknoNew, xldata->offnumNew);
474 
475  PageSetLSN(page, lsn);
476  MarkBufferDirty(buffer);
477  }
478  if (BufferIsValid(buffer))
479  UnlockReleaseBuffer(buffer);
480  }
481  }
482 }
static void fillFakeState(SpGistState *state, spgxlogState stateSrc)
Definition: spgxlog.c:37
void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN, BlockNumber blkno, OffsetNumber offset)
Definition: spgdoinsert.c:50
SpGistInnerTupleData * SpGistInnerTuple
SpGistDeadTuple spgFormDeadTuple(SpGistState *state, int tupstate, BlockNumber blkno, OffsetNumber offnum)
Definition: spgutils.c:754
#define SPGIST_REDIRECT
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:727
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
#define SPGIST_PLACEHOLDER
Pointer Item
Definition: item.h:17
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:223
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
uint32 BlockNumber
Definition: block.h:31
static void addOrReplaceTuple(Page page, Item tuple, int size, OffsetNumber offset)
Definition: spgxlog.c:52
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
OffsetNumber offnum
Definition: spgxlog.h:105
OffsetNumber offnumNew
Definition: spgxlog.h:111
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
spgxlogState stateSrc
Definition: spgxlog.h:130
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
int8 parentBlk
Definition: spgxlog.h:125
uint16 nodeI
Definition: spgxlog.h:128
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1307
bool newPage
Definition: spgxlog.h:112
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
OffsetNumber offnumParent
Definition: spgxlog.h:126
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
Definition: regguts.h:298
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
XLogRedoAction
Definition: xlogutils.h:27
#define InvalidBlockNumber
Definition: block.h:33
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define SpGistPageGetOpaque(page)
struct spgxlogAddNode spgxlogAddNode
#define elog
Definition: elog.h:219
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
static void spgRedoCreateIndex ( XLogReaderState record)
static

Definition at line 76 of file spgxlog.c.

References Assert, buffer, BufferGetBlockNumber(), BufferGetPage, XLogReaderState::EndRecPtr, MarkBufferDirty(), PageSetLSN, SPGIST_LEAF, SPGIST_METAPAGE_BLKNO, SPGIST_NULL_BLKNO, SPGIST_NULLS, SPGIST_ROOT_BLKNO, SpGistInitBuffer(), SpGistInitMetapage(), UnlockReleaseBuffer(), and XLogInitBufferForRedo().

Referenced by spg_redo().

77 {
78  XLogRecPtr lsn = record->EndRecPtr;
79  Buffer buffer;
80  Page page;
81 
82  buffer = XLogInitBufferForRedo(record, 0);
84  page = (Page) BufferGetPage(buffer);
85  SpGistInitMetapage(page);
86  PageSetLSN(page, lsn);
87  MarkBufferDirty(buffer);
88  UnlockReleaseBuffer(buffer);
89 
90  buffer = XLogInitBufferForRedo(record, 1);
93  page = (Page) BufferGetPage(buffer);
94  PageSetLSN(page, lsn);
95  MarkBufferDirty(buffer);
96  UnlockReleaseBuffer(buffer);
97 
98  buffer = XLogInitBufferForRedo(record, 2);
101  page = (Page) BufferGetPage(buffer);
102  PageSetLSN(page, lsn);
103  MarkBufferDirty(buffer);
104  UnlockReleaseBuffer(buffer);
105 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
#define SPGIST_NULLS
#define SPGIST_ROOT_BLKNO
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
#define SPGIST_NULL_BLKNO
#define SPGIST_METAPAGE_BLKNO
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
void SpGistInitMetapage(Page page)
Definition: spgutils.c:524
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2605
#define SPGIST_LEAF
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
static void spgRedoMoveLeafs ( XLogReaderState record)
static

Definition at line 205 of file spgxlog.c.

References addOrReplaceTuple(), BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, fillFakeState(), i, SpGistState::isBuild, MarkBufferDirty(), spgxlogMoveLeafs::newPage, spgxlogMoveLeafs::nMoves, spgxlogMoveLeafs::nodeI, NULL, spgxlogMoveLeafs::offnumParent, PageGetItem, PageGetItemId, PageSetLSN, spgxlogMoveLeafs::replaceDead, SpGistLeafTupleData::size, SizeOfSpgxlogMoveLeafs, SPGIST_LEAF, SPGIST_NULLS, SPGIST_PLACEHOLDER, SPGIST_REDIRECT, SpGistInitBuffer(), spgPageIndexMultiDelete(), spgUpdateNodeLink(), spgxlogMoveLeafs::stateSrc, spgxlogMoveLeafs::storesNulls, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockTag(), and XLogRecGetData.

Referenced by spg_redo().

206 {
207  XLogRecPtr lsn = record->EndRecPtr;
208  char *ptr = XLogRecGetData(record);
209  spgxlogMoveLeafs *xldata = (spgxlogMoveLeafs *) ptr;
211  OffsetNumber *toDelete;
212  OffsetNumber *toInsert;
213  int nInsert;
214  Buffer buffer;
215  Page page;
216  XLogRedoAction action;
217  BlockNumber blknoDst;
218 
219  XLogRecGetBlockTag(record, 1, NULL, NULL, &blknoDst);
220 
221  fillFakeState(&state, xldata->stateSrc);
222 
223  nInsert = xldata->replaceDead ? 1 : xldata->nMoves + 1;
224 
225  ptr += SizeOfSpgxlogMoveLeafs;
226  toDelete = (OffsetNumber *) ptr;
227  ptr += sizeof(OffsetNumber) * xldata->nMoves;
228  toInsert = (OffsetNumber *) ptr;
229  ptr += sizeof(OffsetNumber) * nInsert;
230 
231  /* now ptr points to the list of leaf tuples */
232 
233  /*
234  * In normal operation we would have all three pages (source, dest, and
235  * parent) locked simultaneously; but in WAL replay it should be safe to
236  * update them one at a time, as long as we do it in the right order.
237  */
238 
239  /* Insert tuples on the dest page (do first, so redirect is valid) */
240  if (xldata->newPage)
241  {
242  buffer = XLogInitBufferForRedo(record, 1);
243  SpGistInitBuffer(buffer,
244  SPGIST_LEAF | (xldata->storesNulls ? SPGIST_NULLS : 0));
245  action = BLK_NEEDS_REDO;
246  }
247  else
248  action = XLogReadBufferForRedo(record, 1, &buffer);
249 
250  if (action == BLK_NEEDS_REDO)
251  {
252  int i;
253 
254  page = BufferGetPage(buffer);
255 
256  for (i = 0; i < nInsert; i++)
257  {
258  char *leafTuple;
259  SpGistLeafTupleData leafTupleHdr;
260 
261  /*
262  * the tuples are not aligned, so must copy to access the size
263  * field.
264  */
265  leafTuple = ptr;
266  memcpy(&leafTupleHdr, leafTuple,
267  sizeof(SpGistLeafTupleData));
268 
269  addOrReplaceTuple(page, (Item) leafTuple,
270  leafTupleHdr.size, toInsert[i]);
271  ptr += leafTupleHdr.size;
272  }
273 
274  PageSetLSN(page, lsn);
275  MarkBufferDirty(buffer);
276  }
277  if (BufferIsValid(buffer))
278  UnlockReleaseBuffer(buffer);
279 
280  /* Delete tuples from the source page, inserting a redirection pointer */
281  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
282  {
283  page = BufferGetPage(buffer);
284 
285  spgPageIndexMultiDelete(&state, page, toDelete, xldata->nMoves,
288  blknoDst,
289  toInsert[nInsert - 1]);
290 
291  PageSetLSN(page, lsn);
292  MarkBufferDirty(buffer);
293  }
294  if (BufferIsValid(buffer))
295  UnlockReleaseBuffer(buffer);
296 
297  /* And update the parent downlink */
298  if (XLogReadBufferForRedo(record, 2, &buffer) == BLK_NEEDS_REDO)
299  {
300  SpGistInnerTuple tuple;
301 
302  page = BufferGetPage(buffer);
303 
304  tuple = (SpGistInnerTuple) PageGetItem(page,
305  PageGetItemId(page, xldata->offnumParent));
306 
307  spgUpdateNodeLink(tuple, xldata->nodeI,
308  blknoDst, toInsert[nInsert - 1]);
309 
310  PageSetLSN(page, lsn);
311  MarkBufferDirty(buffer);
312  }
313  if (BufferIsValid(buffer))
314  UnlockReleaseBuffer(buffer);
315 }
static void fillFakeState(SpGistState *state, spgxlogState stateSrc)
Definition: spgxlog.c:37
void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN, BlockNumber blkno, OffsetNumber offset)
Definition: spgdoinsert.c:50
SpGistInnerTupleData * SpGistInnerTuple
#define SPGIST_REDIRECT
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
uint16 nodeI
Definition: spgxlog.h:73
#define SizeOfSpgxlogMoveLeafs
Definition: spgxlog.h:91
#define SPGIST_PLACEHOLDER
#define SPGIST_NULLS
Pointer Item
Definition: item.h:17
uint32 BlockNumber
Definition: block.h:31
static void addOrReplaceTuple(Page page, Item tuple, int size, OffsetNumber offset)
Definition: spgxlog.c:52
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void spgPageIndexMultiDelete(SpGistState *state, Page page, OffsetNumber *itemnos, int nitems, int firststate, int reststate, BlockNumber blkno, OffsetNumber offnum)
Definition: spgdoinsert.c:131
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
spgxlogState stateSrc
Definition: spgxlog.h:75
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
bool replaceDead
Definition: spgxlog.h:68
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1307
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
Definition: regguts.h:298
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
XLogRedoAction
Definition: xlogutils.h:27
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
int i
OffsetNumber offnumParent
Definition: spgxlog.h:72
bool storesNulls
Definition: spgxlog.h:69
uint16 nMoves
Definition: spgxlog.h:66
#define SPGIST_LEAF
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
static void spgRedoPickSplit ( XLogReaderState record)
static

Definition at line 563 of file spgxlog.c.

References addOrReplaceTuple(), Assert, BLK_NEEDS_REDO, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, fillFakeState(), i, spgxlogPickSplit::initDest, spgxlogPickSplit::initInner, spgxlogPickSplit::initSrc, spgxlogPickSplit::innerIsParent, InvalidBlockNumber, InvalidBuffer, InvalidOffsetNumber, SpGistState::isBuild, spgxlogPickSplit::isRootSplit, MarkBufferDirty(), spgxlogPickSplit::nDelete, spgxlogPickSplit::nInsert, spgxlogPickSplit::nodeI, NULL, spgxlogPickSplit::offnumInner, spgxlogPickSplit::offnumParent, PageGetItem, PageGetItemId, PageSetLSN, SpGistInnerTupleData::size, SpGistLeafTupleData::size, SizeOfSpgxlogPickSplit, SPGIST_LEAF, SPGIST_NULLS, SPGIST_PLACEHOLDER, SPGIST_REDIRECT, SpGistInitBuffer(), spgPageIndexMultiDelete(), spgUpdateNodeLink(), spgxlogPickSplit::stateSrc, spgxlogPickSplit::storesNulls, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockTag(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by spg_redo().

564 {
565  XLogRecPtr lsn = record->EndRecPtr;
566  char *ptr = XLogRecGetData(record);
567  spgxlogPickSplit *xldata = (spgxlogPickSplit *) ptr;
568  char *innerTuple;
569  SpGistInnerTupleData innerTupleHdr;
571  OffsetNumber *toDelete;
572  OffsetNumber *toInsert;
573  uint8 *leafPageSelect;
574  Buffer srcBuffer;
575  Buffer destBuffer;
576  Buffer innerBuffer;
577  Page srcPage;
578  Page destPage;
579  Page page;
580  int i;
581  BlockNumber blknoInner;
582  XLogRedoAction action;
583 
584  XLogRecGetBlockTag(record, 2, NULL, NULL, &blknoInner);
585 
586  fillFakeState(&state, xldata->stateSrc);
587 
588  ptr += SizeOfSpgxlogPickSplit;
589  toDelete = (OffsetNumber *) ptr;
590  ptr += sizeof(OffsetNumber) * xldata->nDelete;
591  toInsert = (OffsetNumber *) ptr;
592  ptr += sizeof(OffsetNumber) * xldata->nInsert;
593  leafPageSelect = (uint8 *) ptr;
594  ptr += sizeof(uint8) * xldata->nInsert;
595 
596  innerTuple = ptr;
597  /* the inner tuple is unaligned, so make a copy to access its header */
598  memcpy(&innerTupleHdr, innerTuple, sizeof(SpGistInnerTupleData));
599  ptr += innerTupleHdr.size;
600 
601  /* now ptr points to the list of leaf tuples */
602 
603  if (xldata->isRootSplit)
604  {
605  /* when splitting root, we touch it only in the guise of new inner */
606  srcBuffer = InvalidBuffer;
607  srcPage = NULL;
608  }
609  else if (xldata->initSrc)
610  {
611  /* just re-init the source page */
612  srcBuffer = XLogInitBufferForRedo(record, 0);
613  srcPage = (Page) BufferGetPage(srcBuffer);
614 
615  SpGistInitBuffer(srcBuffer,
616  SPGIST_LEAF | (xldata->storesNulls ? SPGIST_NULLS : 0));
617  /* don't update LSN etc till we're done with it */
618  }
619  else
620  {
621  /*
622  * Delete the specified tuples from source page. (In case we're in
623  * Hot Standby, we need to hold lock on the page till we're done
624  * inserting leaf tuples and the new inner tuple, else the added
625  * redirect tuple will be a dangling link.)
626  */
627  srcPage = NULL;
628  if (XLogReadBufferForRedo(record, 0, &srcBuffer) == BLK_NEEDS_REDO)
629  {
630  srcPage = BufferGetPage(srcBuffer);
631 
632  /*
633  * We have it a bit easier here than in doPickSplit(), because we
634  * know the inner tuple's location already, so we can inject the
635  * correct redirection tuple now.
636  */
637  if (!state.isBuild)
638  spgPageIndexMultiDelete(&state, srcPage,
639  toDelete, xldata->nDelete,
642  blknoInner,
643  xldata->offnumInner);
644  else
645  spgPageIndexMultiDelete(&state, srcPage,
646  toDelete, xldata->nDelete,
651 
652  /* don't update LSN etc till we're done with it */
653  }
654  }
655 
656  /* try to access dest page if any */
657  if (!XLogRecHasBlockRef(record, 1))
658  {
659  destBuffer = InvalidBuffer;
660  destPage = NULL;
661  }
662  else if (xldata->initDest)
663  {
664  /* just re-init the dest page */
665  destBuffer = XLogInitBufferForRedo(record, 1);
666  destPage = (Page) BufferGetPage(destBuffer);
667 
668  SpGistInitBuffer(destBuffer,
669  SPGIST_LEAF | (xldata->storesNulls ? SPGIST_NULLS : 0));
670  /* don't update LSN etc till we're done with it */
671  }
672  else
673  {
674  /*
675  * We could probably release the page lock immediately in the
676  * full-page-image case, but for safety let's hold it till later.
677  */
678  if (XLogReadBufferForRedo(record, 1, &destBuffer) == BLK_NEEDS_REDO)
679  destPage = (Page) BufferGetPage(destBuffer);
680  else
681  destPage = NULL; /* don't do any page updates */
682  }
683 
684  /* restore leaf tuples to src and/or dest page */
685  for (i = 0; i < xldata->nInsert; i++)
686  {
687  char *leafTuple;
688  SpGistLeafTupleData leafTupleHdr;
689 
690  /* the tuples are not aligned, so must copy to access the size field. */
691  leafTuple = ptr;
692  memcpy(&leafTupleHdr, leafTuple, sizeof(SpGistLeafTupleData));
693  ptr += leafTupleHdr.size;
694 
695  page = leafPageSelect[i] ? destPage : srcPage;
696  if (page == NULL)
697  continue; /* no need to touch this page */
698 
699  addOrReplaceTuple(page, (Item) leafTuple, leafTupleHdr.size,
700  toInsert[i]);
701  }
702 
703  /* Now update src and dest page LSNs if needed */
704  if (srcPage != NULL)
705  {
706  PageSetLSN(srcPage, lsn);
707  MarkBufferDirty(srcBuffer);
708  }
709  if (destPage != NULL)
710  {
711  PageSetLSN(destPage, lsn);
712  MarkBufferDirty(destBuffer);
713  }
714 
715  /* restore new inner tuple */
716  if (xldata->initInner)
717  {
718  innerBuffer = XLogInitBufferForRedo(record, 2);
719  SpGistInitBuffer(innerBuffer, (xldata->storesNulls ? SPGIST_NULLS : 0));
720  action = BLK_NEEDS_REDO;
721  }
722  else
723  action = XLogReadBufferForRedo(record, 2, &innerBuffer);
724 
725  if (action == BLK_NEEDS_REDO)
726  {
727  page = BufferGetPage(innerBuffer);
728 
729  addOrReplaceTuple(page, (Item) innerTuple, innerTupleHdr.size,
730  xldata->offnumInner);
731 
732  /* if inner is also parent, update link while we're here */
733  if (xldata->innerIsParent)
734  {
735  SpGistInnerTuple parent;
736 
737  parent = (SpGistInnerTuple) PageGetItem(page,
738  PageGetItemId(page, xldata->offnumParent));
739  spgUpdateNodeLink(parent, xldata->nodeI,
740  blknoInner, xldata->offnumInner);
741  }
742 
743  PageSetLSN(page, lsn);
744  MarkBufferDirty(innerBuffer);
745  }
746  if (BufferIsValid(innerBuffer))
747  UnlockReleaseBuffer(innerBuffer);
748 
749  /*
750  * Now we can release the leaf-page locks. It's okay to do this before
751  * updating the parent downlink.
752  */
753  if (BufferIsValid(srcBuffer))
754  UnlockReleaseBuffer(srcBuffer);
755  if (BufferIsValid(destBuffer))
756  UnlockReleaseBuffer(destBuffer);
757 
758  /* update parent downlink, unless we did it above */
759  if (XLogRecHasBlockRef(record, 3))
760  {
761  Buffer parentBuffer;
762 
763  if (XLogReadBufferForRedo(record, 3, &parentBuffer) == BLK_NEEDS_REDO)
764  {
765  SpGistInnerTuple parent;
766 
767  page = BufferGetPage(parentBuffer);
768 
769  parent = (SpGistInnerTuple) PageGetItem(page,
770  PageGetItemId(page, xldata->offnumParent));
771  spgUpdateNodeLink(parent, xldata->nodeI,
772  blknoInner, xldata->offnumInner);
773 
774  PageSetLSN(page, lsn);
775  MarkBufferDirty(parentBuffer);
776  }
777  if (BufferIsValid(parentBuffer))
778  UnlockReleaseBuffer(parentBuffer);
779  }
780  else
781  Assert(xldata->innerIsParent || xldata->isRootSplit);
782 }
static void fillFakeState(SpGistState *state, spgxlogState stateSrc)
Definition: spgxlog.c:37
void spgUpdateNodeLink(SpGistInnerTuple tup, int nodeN, BlockNumber blkno, OffsetNumber offset)
Definition: spgdoinsert.c:50
uint16 nDelete
Definition: spgxlog.h:169
SpGistInnerTupleData * SpGistInnerTuple
#define SPGIST_REDIRECT
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
spgxlogState stateSrc
Definition: spgxlog.h:185
#define SizeOfSpgxlogPickSplit
Definition: spgxlog.h:199
#define SPGIST_PLACEHOLDER
#define SPGIST_NULLS
unsigned char uint8
Definition: c.h:266
Pointer Item
Definition: item.h:17
#define InvalidBuffer
Definition: buf.h:25
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:223
uint32 BlockNumber
Definition: block.h:31
uint16 nInsert
Definition: spgxlog.h:170
bool innerIsParent
Definition: spgxlog.h:181
static void addOrReplaceTuple(Page page, Item tuple, int size, OffsetNumber offset)
Definition: spgxlog.c:52
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
uint16 OffsetNumber
Definition: off.h:24
OffsetNumber offnumInner
Definition: spgxlog.h:175
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void spgPageIndexMultiDelete(SpGistState *state, Page page, OffsetNumber *itemnos, int nitems, int firststate, int reststate, BlockNumber blkno, OffsetNumber offnum)
Definition: spgdoinsert.c:131
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
OffsetNumber offnumParent
Definition: spgxlog.h:182
uint16 nodeI
Definition: spgxlog.h:183
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1307
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
Definition: regguts.h:298
XLogRedoAction
Definition: xlogutils.h:27
#define InvalidBlockNumber
Definition: block.h:33
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
int i
bool storesNulls
Definition: spgxlog.h:178
#define SPGIST_LEAF
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
bool isRootSplit
Definition: spgxlog.h:167
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
static void spgRedoSplitTuple ( XLogReaderState record)
static

Definition at line 485 of file spgxlog.c.

References addOrReplaceTuple(), BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, MarkBufferDirty(), spgxlogSplitTuple::newPage, spgxlogSplitTuple::offnumPostfix, spgxlogSplitTuple::offnumPrefix, PageAddItem, PageIndexTupleDelete(), PageSetLSN, spgxlogSplitTuple::postfixBlkSame, SpGistInnerTupleData::size, SpGistInitBuffer(), UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by spg_redo().

486 {
487  XLogRecPtr lsn = record->EndRecPtr;
488  char *ptr = XLogRecGetData(record);
489  spgxlogSplitTuple *xldata = (spgxlogSplitTuple *) ptr;
490  char *prefixTuple;
491  SpGistInnerTupleData prefixTupleHdr;
492  char *postfixTuple;
493  SpGistInnerTupleData postfixTupleHdr;
494  Buffer buffer;
495  Page page;
496  XLogRedoAction action;
497 
498  ptr += sizeof(spgxlogSplitTuple);
499  prefixTuple = ptr;
500  /* the prefix tuple is unaligned, so make a copy to access its header */
501  memcpy(&prefixTupleHdr, prefixTuple, sizeof(SpGistInnerTupleData));
502  ptr += prefixTupleHdr.size;
503  postfixTuple = ptr;
504  /* postfix tuple is also unaligned */
505  memcpy(&postfixTupleHdr, postfixTuple, sizeof(SpGistInnerTupleData));
506 
507  /*
508  * In normal operation we would have both pages locked simultaneously; but
509  * in WAL replay it should be safe to update them one at a time, as long
510  * as we do it in the right order.
511  */
512 
513  /* insert postfix tuple first to avoid dangling link */
514  if (!xldata->postfixBlkSame)
515  {
516  if (xldata->newPage)
517  {
518  buffer = XLogInitBufferForRedo(record, 1);
519  /* SplitTuple is not used for nulls pages */
520  SpGistInitBuffer(buffer, 0);
521  action = BLK_NEEDS_REDO;
522  }
523  else
524  action = XLogReadBufferForRedo(record, 1, &buffer);
525  if (action == BLK_NEEDS_REDO)
526  {
527  page = BufferGetPage(buffer);
528 
529  addOrReplaceTuple(page, (Item) postfixTuple,
530  postfixTupleHdr.size, xldata->offnumPostfix);
531 
532  PageSetLSN(page, lsn);
533  MarkBufferDirty(buffer);
534  }
535  if (BufferIsValid(buffer))
536  UnlockReleaseBuffer(buffer);
537  }
538 
539  /* now handle the original page */
540  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
541  {
542  page = BufferGetPage(buffer);
543 
544  PageIndexTupleDelete(page, xldata->offnumPrefix);
545  if (PageAddItem(page, (Item) prefixTuple, prefixTupleHdr.size,
546  xldata->offnumPrefix, false, false) != xldata->offnumPrefix)
547  elog(ERROR, "failed to add item of size %u to SPGiST index page",
548  prefixTupleHdr.size);
549 
550  if (xldata->postfixBlkSame)
551  addOrReplaceTuple(page, (Item) postfixTuple,
552  postfixTupleHdr.size,
553  xldata->offnumPostfix);
554 
555  PageSetLSN(page, lsn);
556  MarkBufferDirty(buffer);
557  }
558  if (BufferIsValid(buffer))
559  UnlockReleaseBuffer(buffer);
560 }
OffsetNumber offnumPostfix
Definition: spgxlog.h:147
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:727
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:412
static void addOrReplaceTuple(Page page, Item tuple, int size, OffsetNumber offset)
Definition: spgxlog.c:52
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define ERROR
Definition: elog.h:43
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:302
void SpGistInitBuffer(Buffer b, uint16 f)
Definition: spgutils.c:514
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
OffsetNumber offnumPrefix
Definition: spgxlog.h:144
bool postfixBlkSame
Definition: spgxlog.h:149
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
uint64 XLogRecPtr
Definition: xlogdefs.h:21
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
XLogRedoAction
Definition: xlogutils.h:27
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define elog
Definition: elog.h:219
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
struct spgxlogSplitTuple spgxlogSplitTuple
Pointer Page
Definition: bufpage.h:74
static void spgRedoVacuumLeaf ( XLogReaderState record)
static

Definition at line 785 of file spgxlog.c.

References Assert, BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, fillFakeState(), i, InvalidBlockNumber, InvalidOffsetNumber, MarkBufferDirty(), spgxlogVacuumLeaf::nChain, spgxlogVacuumLeaf::nDead, SpGistLeafTupleData::nextOffset, spgxlogVacuumLeaf::nMove, spgxlogVacuumLeaf::nPlaceholder, PageGetItem, PageGetItemId, PageSetLSN, SizeOfSpgxlogVacuumLeaf, SPGIST_DEAD, SPGIST_LIVE, SPGIST_PLACEHOLDER, spgPageIndexMultiDelete(), spgxlogVacuumLeaf::stateSrc, SpGistLeafTupleData::tupstate, UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by spg_redo().

786 {
787  XLogRecPtr lsn = record->EndRecPtr;
788  char *ptr = XLogRecGetData(record);
789  spgxlogVacuumLeaf *xldata = (spgxlogVacuumLeaf *) ptr;
790  OffsetNumber *toDead;
791  OffsetNumber *toPlaceholder;
792  OffsetNumber *moveSrc;
793  OffsetNumber *moveDest;
794  OffsetNumber *chainSrc;
795  OffsetNumber *chainDest;
797  Buffer buffer;
798  Page page;
799  int i;
800 
801  fillFakeState(&state, xldata->stateSrc);
802 
804  toDead = (OffsetNumber *) ptr;
805  ptr += sizeof(OffsetNumber) * xldata->nDead;
806  toPlaceholder = (OffsetNumber *) ptr;
807  ptr += sizeof(OffsetNumber) * xldata->nPlaceholder;
808  moveSrc = (OffsetNumber *) ptr;
809  ptr += sizeof(OffsetNumber) * xldata->nMove;
810  moveDest = (OffsetNumber *) ptr;
811  ptr += sizeof(OffsetNumber) * xldata->nMove;
812  chainSrc = (OffsetNumber *) ptr;
813  ptr += sizeof(OffsetNumber) * xldata->nChain;
814  chainDest = (OffsetNumber *) ptr;
815 
816  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
817  {
818  page = BufferGetPage(buffer);
819 
820  spgPageIndexMultiDelete(&state, page,
821  toDead, xldata->nDead,
825 
826  spgPageIndexMultiDelete(&state, page,
827  toPlaceholder, xldata->nPlaceholder,
831 
832  /* see comments in vacuumLeafPage() */
833  for (i = 0; i < xldata->nMove; i++)
834  {
835  ItemId idSrc = PageGetItemId(page, moveSrc[i]);
836  ItemId idDest = PageGetItemId(page, moveDest[i]);
837  ItemIdData tmp;
838 
839  tmp = *idSrc;
840  *idSrc = *idDest;
841  *idDest = tmp;
842  }
843 
844  spgPageIndexMultiDelete(&state, page,
845  moveSrc, xldata->nMove,
849 
850  for (i = 0; i < xldata->nChain; i++)
851  {
852  SpGistLeafTuple lt;
853 
854  lt = (SpGistLeafTuple) PageGetItem(page,
855  PageGetItemId(page, chainSrc[i]));
856  Assert(lt->tupstate == SPGIST_LIVE);
857  lt->nextOffset = chainDest[i];
858  }
859 
860  PageSetLSN(page, lsn);
861  MarkBufferDirty(buffer);
862  }
863  if (BufferIsValid(buffer))
864  UnlockReleaseBuffer(buffer);
865 }
#define SPGIST_DEAD
static void fillFakeState(SpGistState *state, spgxlogState stateSrc)
Definition: spgxlog.c:37
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
#define SPGIST_PLACEHOLDER
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void spgPageIndexMultiDelete(SpGistState *state, Page page, OffsetNumber *itemnos, int nitems, int firststate, int reststate, BlockNumber blkno, OffsetNumber offnum)
Definition: spgdoinsert.c:131
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
spgxlogState stateSrc
Definition: spgxlog.h:208
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
unsigned int tupstate
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
#define SizeOfSpgxlogVacuumLeaf
Definition: spgxlog.h:223
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
uint16 nPlaceholder
Definition: spgxlog.h:204
Definition: regguts.h:298
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define SPGIST_LIVE
#define InvalidBlockNumber
Definition: block.h:33
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
OffsetNumber nextOffset
int i
SpGistLeafTupleData * SpGistLeafTuple
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
static void spgRedoVacuumRedirect ( XLogReaderState record)
static

Definition at line 894 of file spgxlog.c.

References Assert, BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, spgxlogVacuumRedirect::firstPlaceholder, i, InHotStandby, InvalidOffsetNumber, ItemPointerSetInvalid, MarkBufferDirty(), spgxlogVacuumRedirect::newestRedirectXid, SpGistPageOpaqueData::nPlaceholder, SpGistPageOpaqueData::nRedirection, spgxlogVacuumRedirect::nToPlaceholder, NULL, spgxlogVacuumRedirect::offsets, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageIndexMultiDelete(), PageSetLSN, palloc(), pfree(), SpGistDeadTupleData::pointer, ResolveRecoveryConflictWithSnapshot(), SPGIST_PLACEHOLDER, SPGIST_REDIRECT, SpGistPageGetOpaque, TransactionIdIsValid, SpGistDeadTupleData::tupstate, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockTag(), and XLogRecGetData.

Referenced by spg_redo().

895 {
896  XLogRecPtr lsn = record->EndRecPtr;
897  char *ptr = XLogRecGetData(record);
899  OffsetNumber *itemToPlaceholder;
900  Buffer buffer;
901 
902  itemToPlaceholder = xldata->offsets;
903 
904  /*
905  * If any redirection tuples are being removed, make sure there are no
906  * live Hot Standby transactions that might need to see them.
907  */
908  if (InHotStandby)
909  {
911  {
912  RelFileNode node;
913 
914  XLogRecGetBlockTag(record, 0, &node, NULL, NULL);
916  node);
917  }
918  }
919 
920  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
921  {
922  Page page = BufferGetPage(buffer);
923  SpGistPageOpaque opaque = SpGistPageGetOpaque(page);
924  int i;
925 
926  /* Convert redirect pointers to plain placeholders */
927  for (i = 0; i < xldata->nToPlaceholder; i++)
928  {
929  SpGistDeadTuple dt;
930 
931  dt = (SpGistDeadTuple) PageGetItem(page,
932  PageGetItemId(page, itemToPlaceholder[i]));
936  }
937 
938  Assert(opaque->nRedirection >= xldata->nToPlaceholder);
939  opaque->nRedirection -= xldata->nToPlaceholder;
940  opaque->nPlaceholder += xldata->nToPlaceholder;
941 
942  /* Remove placeholder tuples at end of page */
943  if (xldata->firstPlaceholder != InvalidOffsetNumber)
944  {
945  int max = PageGetMaxOffsetNumber(page);
946  OffsetNumber *toDelete;
947 
948  toDelete = palloc(sizeof(OffsetNumber) * max);
949 
950  for (i = xldata->firstPlaceholder; i <= max; i++)
951  toDelete[i - xldata->firstPlaceholder] = i;
952 
953  i = max - xldata->firstPlaceholder + 1;
954  Assert(opaque->nPlaceholder >= i);
955  opaque->nPlaceholder -= i;
956 
957  /* The array is sorted, so can use PageIndexMultiDelete */
958  PageIndexMultiDelete(page, toDelete, i);
959 
960  pfree(toDelete);
961  }
962 
963  PageSetLSN(page, lsn);
964  MarkBufferDirty(buffer);
965  }
966  if (BufferIsValid(buffer))
967  UnlockReleaseBuffer(buffer);
968 }
#define SPGIST_REDIRECT
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
#define SPGIST_PLACEHOLDER
OffsetNumber firstPlaceholder
Definition: spgxlog.h:241
#define InHotStandby
Definition: xlog.h:74
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:353
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
uint16 OffsetNumber
Definition: off.h:24
TransactionId newestRedirectXid
Definition: spgxlog.h:242
void pfree(void *pointer)
Definition: mcxt.c:950
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
ItemPointerData pointer
OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]
Definition: spgxlog.h:245
SpGistDeadTupleData * SpGistDeadTuple
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:231
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1307
unsigned int tupstate
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
#define NULL
Definition: c.h:229
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:675
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:836
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
#define SpGistPageGetOpaque(page)
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
void * palloc(Size size)
Definition: mcxt.c:849
int i
void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
Definition: standby.c:267
#define TransactionIdIsValid(xid)
Definition: transam.h:41
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:336
Pointer Page
Definition: bufpage.h:74
static void spgRedoVacuumRoot ( XLogReaderState record)
static

Definition at line 868 of file spgxlog.c.

References BLK_NEEDS_REDO, buffer, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, MarkBufferDirty(), spgxlogVacuumRoot::nDelete, spgxlogVacuumRoot::offsets, PageIndexMultiDelete(), PageSetLSN, UnlockReleaseBuffer(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by spg_redo().

869 {
870  XLogRecPtr lsn = record->EndRecPtr;
871  char *ptr = XLogRecGetData(record);
872  spgxlogVacuumRoot *xldata = (spgxlogVacuumRoot *) ptr;
873  OffsetNumber *toDelete;
874  Buffer buffer;
875  Page page;
876 
877  toDelete = xldata->offsets;
878 
879  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
880  {
881  page = BufferGetPage(buffer);
882 
883  /* The tuple numbers are in order */
884  PageIndexMultiDelete(page, toDelete, xldata->nDelete);
885 
886  PageSetLSN(page, lsn);
887  MarkBufferDirty(buffer);
888  }
889  if (BufferIsValid(buffer))
890  UnlockReleaseBuffer(buffer);
891 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1450
uint16 nDelete
Definition: spgxlog.h:228
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:220
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3332
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:290
uint64 XLogRecPtr
Definition: xlogdefs.h:21
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:836
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]
Definition: spgxlog.h:233
#define PageSetLSN(page, lsn)
Definition: bufpage.h:364
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74

Variable Documentation

MemoryContext opCtx
static

Definition at line 27 of file spgxlog.c.