PostgreSQL Source Code  git master
nbtxlog.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/nbtree.h"
#include "access/nbtxlog.h"
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xlogutils.h"
#include "miscadmin.h"
#include "storage/procarray.h"
#include "utils/memutils.h"
Include dependency graph for nbtxlog.c:

Go to the source code of this file.

Functions

static void _bt_restore_page (Page page, char *from, int len)
 
static void _bt_restore_meta (XLogReaderState *record, uint8 block_id)
 
static void _bt_clear_incomplete_split (XLogReaderState *record, uint8 block_id)
 
static void btree_xlog_insert (bool isleaf, bool ismeta, bool posting, XLogReaderState *record)
 
static void btree_xlog_split (bool newitemonleft, XLogReaderState *record)
 
static void btree_xlog_dedup (XLogReaderState *record)
 
static void btree_xlog_updates (Page page, OffsetNumber *updatedoffsets, xl_btree_update *updates, int nupdated)
 
static void btree_xlog_vacuum (XLogReaderState *record)
 
static void btree_xlog_delete (XLogReaderState *record)
 
static void btree_xlog_mark_page_halfdead (uint8 info, XLogReaderState *record)
 
static void btree_xlog_unlink_page (uint8 info, XLogReaderState *record)
 
static void btree_xlog_newroot (XLogReaderState *record)
 
static void btree_xlog_reuse_page (XLogReaderState *record)
 
void btree_redo (XLogReaderState *record)
 
void btree_xlog_startup (void)
 
void btree_xlog_cleanup (void)
 
void btree_mask (char *pagedata, BlockNumber blkno)
 

Variables

static MemoryContext opCtx
 

Function Documentation

◆ _bt_clear_incomplete_split()

static void _bt_clear_incomplete_split ( XLogReaderState record,
uint8  block_id 
)
static

Definition at line 142 of file nbtxlog.c.

References Assert, BLK_NEEDS_REDO, BTP_INCOMPLETE_SPLIT, BTPageOpaqueData::btpo_flags, buf, BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, MarkBufferDirty(), P_INCOMPLETE_SPLIT, PageGetSpecialPointer, PageSetLSN, UnlockReleaseBuffer(), and XLogReadBufferForRedo().

Referenced by btree_xlog_insert(), btree_xlog_newroot(), and btree_xlog_split().

143 {
144  XLogRecPtr lsn = record->EndRecPtr;
145  Buffer buf;
146 
147  if (XLogReadBufferForRedo(record, block_id, &buf) == BLK_NEEDS_REDO)
148  {
149  Page page = (Page) BufferGetPage(buf);
151 
152  Assert(P_INCOMPLETE_SPLIT(pageop));
153  pageop->btpo_flags &= ~BTP_INCOMPLETE_SPLIT;
154 
155  PageSetLSN(page, lsn);
156  MarkBufferDirty(buf);
157  }
158  if (BufferIsValid(buf))
159  UnlockReleaseBuffer(buf);
160 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
#define BTP_INCOMPLETE_SPLIT
Definition: nbtree.h:81
#define P_INCOMPLETE_SPLIT(opaque)
Definition: nbtree.h:226
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
static char * buf
Definition: pg_test_fsync.c:68
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78

◆ _bt_restore_meta()

static void _bt_restore_meta ( XLogReaderState record,
uint8  block_id 
)
static

Definition at line 85 of file nbtxlog.c.

References _bt_pageinit(), xl_btree_metadata::allequalimage, Assert, BTMetaPageData::btm_allequalimage, BTMetaPageData::btm_fastlevel, BTMetaPageData::btm_fastroot, BTMetaPageData::btm_last_cleanup_num_delpages, BTMetaPageData::btm_last_cleanup_num_heap_tuples, BTMetaPageData::btm_level, BTMetaPageData::btm_magic, BTMetaPageData::btm_root, BTMetaPageData::btm_version, BTP_META, BTPageGetMeta, BTPageOpaqueData::btpo_flags, BTREE_MAGIC, BTREE_METAPAGE, BTREE_NOVAC_VERSION, BufferGetBlockNumber(), BufferGetPage, BufferGetPageSize, XLogReaderState::EndRecPtr, xl_btree_metadata::fastlevel, xl_btree_metadata::fastroot, xl_btree_metadata::last_cleanup_num_delpages, xl_btree_metadata::level, MarkBufferDirty(), PageGetSpecialPointer, PageSetLSN, xl_btree_metadata::root, UnlockReleaseBuffer(), xl_btree_metadata::version, XLogInitBufferForRedo(), and XLogRecGetBlockData().

Referenced by btree_redo(), btree_xlog_insert(), btree_xlog_newroot(), and btree_xlog_unlink_page().

86 {
87  XLogRecPtr lsn = record->EndRecPtr;
88  Buffer metabuf;
89  Page metapg;
90  BTMetaPageData *md;
91  BTPageOpaque pageop;
92  xl_btree_metadata *xlrec;
93  char *ptr;
94  Size len;
95 
96  metabuf = XLogInitBufferForRedo(record, block_id);
97  ptr = XLogRecGetBlockData(record, block_id, &len);
98 
99  Assert(len == sizeof(xl_btree_metadata));
101  xlrec = (xl_btree_metadata *) ptr;
102  metapg = BufferGetPage(metabuf);
103 
104  _bt_pageinit(metapg, BufferGetPageSize(metabuf));
105 
106  md = BTPageGetMeta(metapg);
107  md->btm_magic = BTREE_MAGIC;
108  md->btm_version = xlrec->version;
109  md->btm_root = xlrec->root;
110  md->btm_level = xlrec->level;
111  md->btm_fastroot = xlrec->fastroot;
112  md->btm_fastlevel = xlrec->fastlevel;
113  /* Cannot log BTREE_MIN_VERSION index metapage without upgrade */
117  md->btm_allequalimage = xlrec->allequalimage;
118 
119  pageop = (BTPageOpaque) PageGetSpecialPointer(metapg);
120  pageop->btpo_flags = BTP_META;
121 
122  /*
123  * Set pd_lower just past the end of the metadata. This is essential,
124  * because without doing so, metadata will be lost if xlog.c compresses
125  * the page.
126  */
127  ((PageHeader) metapg)->pd_lower =
128  ((char *) md + sizeof(BTMetaPageData)) - (char *) metapg;
129 
130  PageSetLSN(metapg, lsn);
131  MarkBufferDirty(metabuf);
132  UnlockReleaseBuffer(metabuf);
133 }
bool allequalimage
Definition: nbtxlog.h:57
uint32 last_cleanup_num_delpages
Definition: nbtxlog.h:56
uint32 btm_version
Definition: nbtree.h:104
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
uint32 btm_magic
Definition: nbtree.h:103
BlockNumber root
Definition: nbtxlog.h:52
#define BTP_META
Definition: nbtree.h:77
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
BlockNumber btm_fastroot
Definition: nbtree.h:107
#define BTREE_MAGIC
Definition: nbtree.h:147
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:304
#define BTPageGetMeta(p)
Definition: nbtree.h:119
bool btm_allequalimage
Definition: nbtree.h:116
#define BTREE_NOVAC_VERSION
Definition: nbtree.h:150
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
uint32 btm_last_cleanup_num_delpages
Definition: nbtree.h:112
#define BTREE_METAPAGE
Definition: nbtree.h:146
uint32 version
Definition: nbtxlog.h:51
uint32 btm_fastlevel
Definition: nbtree.h:108
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
BlockNumber btm_root
Definition: nbtree.h:105
PageHeaderData * PageHeader
Definition: bufpage.h:166
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
size_t Size
Definition: c.h:540
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
float8 btm_last_cleanup_num_heap_tuples
Definition: nbtree.h:114
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2758
uint32 fastlevel
Definition: nbtxlog.h:55
uint32 btm_level
Definition: nbtree.h:106
uint32 level
Definition: nbtxlog.h:53
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:1142
BlockNumber fastroot
Definition: nbtxlog.h:54
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78

◆ _bt_restore_page()

static void _bt_restore_page ( Page  page,
char *  from,
int  len 
)
static

Definition at line 38 of file nbtxlog.c.

References elog, i, IndexTupleSize, InvalidOffsetNumber, MAXALIGN, MaxIndexTuplesPerPage, PageAddItem, and PANIC.

Referenced by btree_xlog_newroot(), and btree_xlog_split().

39 {
40  IndexTupleData itupdata;
41  Size itemsz;
42  char *end = from + len;
44  uint16 itemsizes[MaxIndexTuplesPerPage];
45  int i;
46  int nitems;
47 
48  /*
49  * To get the items back in the original order, we add them to the page in
50  * reverse. To figure out where one tuple ends and another begins, we
51  * have to scan them in forward order first.
52  */
53  i = 0;
54  while (from < end)
55  {
56  /*
57  * As we step through the items, 'from' won't always be properly
58  * aligned, so we need to use memcpy(). Further, we use Item (which
59  * is just a char*) here for our items array for the same reason;
60  * wouldn't want the compiler or anyone thinking that an item is
61  * aligned when it isn't.
62  */
63  memcpy(&itupdata, from, sizeof(IndexTupleData));
64  itemsz = IndexTupleSize(&itupdata);
65  itemsz = MAXALIGN(itemsz);
66 
67  items[i] = (Item) from;
68  itemsizes[i] = itemsz;
69  i++;
70 
71  from += itemsz;
72  }
73  nitems = i;
74 
75  for (i = nitems - 1; i >= 0; i--)
76  {
77  if (PageAddItem(page, items[i], itemsizes[i], nitems - i,
78  false, false) == InvalidOffsetNumber)
79  elog(PANIC, "_bt_restore_page: cannot add item to page");
80  from += itemsz;
81  }
82 }
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
#define PANIC
Definition: elog.h:50
unsigned short uint16
Definition: c.h:440
#define InvalidOffsetNumber
Definition: off.h:26
size_t Size
Definition: c.h:540
#define MAXALIGN(LEN)
Definition: c.h:757
#define MaxIndexTuplesPerPage
Definition: itup.h:145
#define elog(elevel,...)
Definition: elog.h:232
int i
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ btree_mask()

void btree_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 1091 of file nbtxlog.c.

References BTP_HAS_GARBAGE, BTP_SPLIT_END, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, mask_lp_flags(), mask_page_hint_bits(), mask_page_lsn_and_checksum(), mask_unused_space(), P_ISLEAF, and PageGetSpecialPointer.

1092 {
1093  Page page = (Page) pagedata;
1094  BTPageOpaque maskopaq;
1095 
1097 
1098  mask_page_hint_bits(page);
1099  mask_unused_space(page);
1100 
1101  maskopaq = (BTPageOpaque) PageGetSpecialPointer(page);
1102 
1103  if (P_ISLEAF(maskopaq))
1104  {
1105  /*
1106  * In btree leaf pages, it is possible to modify the LP_FLAGS without
1107  * emitting any WAL record. Hence, mask the line pointer flags. See
1108  * _bt_killitems(), _bt_check_unique() for details.
1109  */
1110  mask_lp_flags(page);
1111  }
1112 
1113  /*
1114  * BTP_HAS_GARBAGE is just an un-logged hint bit. So, mask it. See
1115  * _bt_delete_or_dedup_one_page(), _bt_killitems(), and _bt_check_unique()
1116  * for details.
1117  */
1118  maskopaq->btpo_flags &= ~BTP_HAS_GARBAGE;
1119 
1120  /*
1121  * During replay of a btree page split, we don't set the BTP_SPLIT_END
1122  * flag of the right sibling and initialize the cycle_id to 0 for the same
1123  * page. See btree_xlog_split() for details.
1124  */
1125  maskopaq->btpo_flags &= ~BTP_SPLIT_END;
1126  maskopaq->btpo_cycleid = 0;
1127 }
#define BTP_SPLIT_END
Definition: nbtree.h:79
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
void mask_unused_space(Page page)
Definition: bufmask.c:71
BTCycleId btpo_cycleid
Definition: nbtree.h:68
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
uint16 btpo_flags
Definition: nbtree.h:67
void mask_lp_flags(Page page)
Definition: bufmask.c:95
#define BTP_HAS_GARBAGE
Definition: nbtree.h:80
Pointer Page
Definition: bufpage.h:78
#define P_ISLEAF(opaque)
Definition: nbtree.h:219

◆ btree_redo()

void btree_redo ( XLogReaderState record)

Definition at line 1014 of file nbtxlog.c.

References _bt_restore_meta(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_reuse_page(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), elog, MemoryContextReset(), MemoryContextSwitchTo(), PANIC, XLOG_BTREE_DEDUP, XLOG_BTREE_DELETE, XLOG_BTREE_INSERT_LEAF, XLOG_BTREE_INSERT_META, XLOG_BTREE_INSERT_POST, XLOG_BTREE_INSERT_UPPER, XLOG_BTREE_MARK_PAGE_HALFDEAD, XLOG_BTREE_META_CLEANUP, XLOG_BTREE_NEWROOT, XLOG_BTREE_REUSE_PAGE, XLOG_BTREE_SPLIT_L, XLOG_BTREE_SPLIT_R, XLOG_BTREE_UNLINK_PAGE, XLOG_BTREE_UNLINK_PAGE_META, XLOG_BTREE_VACUUM, XLogRecGetInfo, and XLR_INFO_MASK.

1015 {
1016  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1017  MemoryContext oldCtx;
1018 
1019  oldCtx = MemoryContextSwitchTo(opCtx);
1020  switch (info)
1021  {
1023  btree_xlog_insert(true, false, false, record);
1024  break;
1026  btree_xlog_insert(false, false, false, record);
1027  break;
1029  btree_xlog_insert(false, true, false, record);
1030  break;
1031  case XLOG_BTREE_SPLIT_L:
1032  btree_xlog_split(true, record);
1033  break;
1034  case XLOG_BTREE_SPLIT_R:
1035  btree_xlog_split(false, record);
1036  break;
1038  btree_xlog_insert(true, false, true, record);
1039  break;
1040  case XLOG_BTREE_DEDUP:
1041  btree_xlog_dedup(record);
1042  break;
1043  case XLOG_BTREE_VACUUM:
1044  btree_xlog_vacuum(record);
1045  break;
1046  case XLOG_BTREE_DELETE:
1047  btree_xlog_delete(record);
1048  break;
1050  btree_xlog_mark_page_halfdead(info, record);
1051  break;
1054  btree_xlog_unlink_page(info, record);
1055  break;
1056  case XLOG_BTREE_NEWROOT:
1057  btree_xlog_newroot(record);
1058  break;
1059  case XLOG_BTREE_REUSE_PAGE:
1060  btree_xlog_reuse_page(record);
1061  break;
1063  _bt_restore_meta(record, 0);
1064  break;
1065  default:
1066  elog(PANIC, "btree_redo: unknown op code %u", info);
1067  }
1068  MemoryContextSwitchTo(oldCtx);
1070 }
static void btree_xlog_vacuum(XLogReaderState *record)
Definition: nbtxlog.c:601
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned char uint8
Definition: c.h:439
#define XLOG_BTREE_INSERT_META
Definition: nbtxlog.h:29
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:143
static void btree_xlog_delete(XLogReaderState *record)
Definition: nbtxlog.c:654
#define PANIC
Definition: elog.h:50
#define XLOG_BTREE_NEWROOT
Definition: nbtxlog.h:37
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
static void btree_xlog_newroot(XLogReaderState *record)
Definition: nbtxlog.c:938
static void btree_xlog_reuse_page(XLogReaderState *record)
Definition: nbtxlog.c:1004
#define XLOG_BTREE_INSERT_LEAF
Definition: nbtxlog.h:27
#define XLOG_BTREE_VACUUM
Definition: nbtxlog.h:39
#define XLOG_BTREE_UNLINK_PAGE
Definition: nbtxlog.h:35
static void btree_xlog_dedup(XLogReaderState *record)
Definition: nbtxlog.c:467
static void btree_xlog_insert(bool isleaf, bool ismeta, bool posting, XLogReaderState *record)
Definition: nbtxlog.c:163
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:305
#define XLOG_BTREE_DELETE
Definition: nbtxlog.h:34
#define XLOG_BTREE_DEDUP
Definition: nbtxlog.h:33
#define XLOG_BTREE_REUSE_PAGE
Definition: nbtxlog.h:41
#define XLOG_BTREE_MARK_PAGE_HALFDEAD
Definition: nbtxlog.h:38
#define XLOG_BTREE_SPLIT_R
Definition: nbtxlog.h:31
static MemoryContext opCtx
Definition: nbtxlog.c:27
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define XLOG_BTREE_INSERT_POST
Definition: nbtxlog.h:32
static void btree_xlog_unlink_page(uint8 info, XLogReaderState *record)
Definition: nbtxlog.c:799
#define XLOG_BTREE_INSERT_UPPER
Definition: nbtxlog.h:28
static void btree_xlog_mark_page_halfdead(uint8 info, XLogReaderState *record)
Definition: nbtxlog.c:714
#define elog(elevel,...)
Definition: elog.h:232
#define XLOG_BTREE_SPLIT_L
Definition: nbtxlog.h:30
#define XLOG_BTREE_UNLINK_PAGE_META
Definition: nbtxlog.h:36
static void btree_xlog_split(bool newitemonleft, XLogReaderState *record)
Definition: nbtxlog.c:254
#define XLOG_BTREE_META_CLEANUP
Definition: nbtxlog.h:43

◆ btree_xlog_cleanup()

void btree_xlog_cleanup ( void  )

Definition at line 1081 of file nbtxlog.c.

References MemoryContextDelete().

1082 {
1084  opCtx = NULL;
1085 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static MemoryContext opCtx
Definition: nbtxlog.c:27

◆ btree_xlog_dedup()

static void btree_xlog_dedup ( XLogReaderState record)
static

Definition at line 467 of file nbtxlog.c.

References _bt_dedup_finish_pending(), _bt_dedup_save_htid(), _bt_dedup_start_pending(), Assert, BTDedupStateData::base, BTDedupInterval::baseoff, BTDedupStateData::baseoff, BTDedupStateData::basetupsize, BLK_NEEDS_REDO, BTMaxItemSize, BTP_HAS_GARBAGE, BTPageOpaqueData::btpo_flags, buf, BufferGetPage, BufferIsValid, BTDedupStateData::deduplicate, elog, XLogReaderState::EndRecPtr, ERROR, BTDedupStateData::htids, intervals, BTDedupStateData::intervals, InvalidOffsetNumber, ItemIdGetLength, MarkBufferDirty(), BTDedupStateData::maxpostingsize, BTDedupStateData::nhtids, xl_btree_dedup::nintervals, BTDedupStateData::nintervals, BTDedupInterval::nitems, BTDedupStateData::nitems, BTDedupStateData::nmaxitems, OffsetNumberNext, P_FIRSTDATAKEY, P_HAS_GARBAGE, P_HIKEY, P_RIGHTMOST, PageAddItem, PageGetItem, PageGetItemId, PageGetMaxOffsetNumber, PageGetSpecialPointer, PageGetTempPageCopySpecial(), PageRestoreTempPage(), PageSetLSN, palloc(), BTDedupStateData::phystupsize, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by btree_redo().

468 {
469  XLogRecPtr lsn = record->EndRecPtr;
470  xl_btree_dedup *xlrec = (xl_btree_dedup *) XLogRecGetData(record);
471  Buffer buf;
472 
473  if (XLogReadBufferForRedo(record, 0, &buf) == BLK_NEEDS_REDO)
474  {
475  char *ptr = XLogRecGetBlockData(record, 0, NULL);
476  Page page = (Page) BufferGetPage(buf);
478  OffsetNumber offnum,
479  minoff,
480  maxoff;
483  Page newpage;
484 
485  state = (BTDedupState) palloc(sizeof(BTDedupStateData));
486  state->deduplicate = true; /* unused */
487  state->nmaxitems = 0; /* unused */
488  /* Conservatively use larger maxpostingsize than primary */
489  state->maxpostingsize = BTMaxItemSize(page);
490  state->base = NULL;
491  state->baseoff = InvalidOffsetNumber;
492  state->basetupsize = 0;
493  state->htids = palloc(state->maxpostingsize);
494  state->nhtids = 0;
495  state->nitems = 0;
496  state->phystupsize = 0;
497  state->nintervals = 0;
498 
499  minoff = P_FIRSTDATAKEY(opaque);
500  maxoff = PageGetMaxOffsetNumber(page);
501  newpage = PageGetTempPageCopySpecial(page);
502 
503  if (!P_RIGHTMOST(opaque))
504  {
505  ItemId itemid = PageGetItemId(page, P_HIKEY);
506  Size itemsz = ItemIdGetLength(itemid);
507  IndexTuple item = (IndexTuple) PageGetItem(page, itemid);
508 
509  if (PageAddItem(newpage, (Item) item, itemsz, P_HIKEY,
510  false, false) == InvalidOffsetNumber)
511  elog(ERROR, "deduplication failed to add highkey");
512  }
513 
514  intervals = (BTDedupInterval *) ptr;
515  for (offnum = minoff;
516  offnum <= maxoff;
517  offnum = OffsetNumberNext(offnum))
518  {
519  ItemId itemid = PageGetItemId(page, offnum);
520  IndexTuple itup = (IndexTuple) PageGetItem(page, itemid);
521 
522  if (offnum == minoff)
523  _bt_dedup_start_pending(state, itup, offnum);
524  else if (state->nintervals < xlrec->nintervals &&
525  state->baseoff == intervals[state->nintervals].baseoff &&
526  state->nitems < intervals[state->nintervals].nitems)
527  {
528  if (!_bt_dedup_save_htid(state, itup))
529  elog(ERROR, "deduplication failed to add heap tid to pending posting list");
530  }
531  else
532  {
533  _bt_dedup_finish_pending(newpage, state);
534  _bt_dedup_start_pending(state, itup, offnum);
535  }
536  }
537 
538  _bt_dedup_finish_pending(newpage, state);
539  Assert(state->nintervals == xlrec->nintervals);
540  Assert(memcmp(state->intervals, intervals,
541  state->nintervals * sizeof(BTDedupInterval)) == 0);
542 
543  if (P_HAS_GARBAGE(opaque))
544  {
545  BTPageOpaque nopaque = (BTPageOpaque) PageGetSpecialPointer(newpage);
546 
547  nopaque->btpo_flags &= ~BTP_HAS_GARBAGE;
548  }
549 
550  PageRestoreTempPage(newpage, page);
551  PageSetLSN(page, lsn);
552  MarkBufferDirty(buf);
553  }
554 
555  if (BufferIsValid(buf))
556  UnlockReleaseBuffer(buf);
557 }
char * intervals[]
IndexTuple base
Definition: nbtree.h:871
void PageRestoreTempPage(Page tempPage, Page oldPage)
Definition: bufpage.c:424
uint16 nintervals
Definition: nbtxlog.h:172
OffsetNumber baseoff
Definition: nbtree.h:872
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:369
Pointer Item
Definition: item.h:17
#define P_HAS_GARBAGE(opaque)
Definition: nbtree.h:225
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
void _bt_dedup_start_pending(BTDedupState state, IndexTuple base, OffsetNumber baseoff)
Definition: nbtdedup.c:423
Size _bt_dedup_finish_pending(Page newpage, BTDedupState state)
Definition: nbtdedup.c:545
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:357
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
Page PageGetTempPageCopySpecial(Page page)
Definition: bufpage.c:402
ItemPointer htids
Definition: nbtree.h:876
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
Size phystupsize
Definition: nbtree.h:879
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
#define ERROR
Definition: elog.h:46
BTDedupInterval intervals[MaxIndexTuplesPerPage]
Definition: nbtree.h:888
static char * buf
Definition: pg_test_fsync.c:68
bool _bt_dedup_save_htid(BTDedupState state, IndexTuple itup)
Definition: nbtdedup.c:474
IndexTupleData * IndexTuple
Definition: itup.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
uint16 nitems
Definition: nbtree.h:842
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
Definition: regguts.h:317
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
size_t Size
Definition: c.h:540
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
Size basetupsize
Definition: nbtree.h:873
Size maxpostingsize
Definition: nbtree.h:868
#define BTMaxItemSize(page)
Definition: nbtree.h:162
#define P_HIKEY
Definition: nbtree.h:367
void * palloc(Size size)
Definition: mcxt.c:1062
bool deduplicate
Definition: nbtree.h:866
#define elog(elevel,...)
Definition: elog.h:232
BTDedupStateData * BTDedupState
Definition: nbtree.h:891
OffsetNumber baseoff
Definition: nbtree.h:841
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define P_RIGHTMOST(opaque)
Definition: nbtree.h:218
#define BTP_HAS_GARBAGE
Definition: nbtree.h:80
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78

◆ btree_xlog_delete()

static void btree_xlog_delete ( XLogReaderState record)
static

Definition at line 654 of file nbtxlog.c.

References BLK_NEEDS_REDO, BTP_HAS_GARBAGE, BTPageOpaqueData::btpo_flags, btree_xlog_updates(), BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, InHotStandby, xl_btree_delete::latestRemovedXid, MarkBufferDirty(), xl_btree_delete::ndeleted, xl_btree_delete::nupdated, PageGetSpecialPointer, PageIndexMultiDelete(), PageSetLSN, ResolveRecoveryConflictWithSnapshot(), UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), XLogRecGetBlockTag(), and XLogRecGetData.

Referenced by btree_redo().

655 {
656  XLogRecPtr lsn = record->EndRecPtr;
657  xl_btree_delete *xlrec = (xl_btree_delete *) XLogRecGetData(record);
658  Buffer buffer;
659  Page page;
660  BTPageOpaque opaque;
661 
662  /*
663  * If we have any conflict processing to do, it must happen before we
664  * update the page
665  */
666  if (InHotStandby)
667  {
668  RelFileNode rnode;
669 
670  XLogRecGetBlockTag(record, 0, &rnode, NULL, NULL);
671 
673  }
674 
675  /*
676  * We don't need to take a cleanup lock to apply these changes. See
677  * nbtree/README for details.
678  */
679  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
680  {
681  char *ptr = XLogRecGetBlockData(record, 0, NULL);
682 
683  page = (Page) BufferGetPage(buffer);
684 
685  if (xlrec->nupdated > 0)
686  {
687  OffsetNumber *updatedoffsets;
688  xl_btree_update *updates;
689 
690  updatedoffsets = (OffsetNumber *)
691  (ptr + xlrec->ndeleted * sizeof(OffsetNumber));
692  updates = (xl_btree_update *) ((char *) updatedoffsets +
693  xlrec->nupdated *
694  sizeof(OffsetNumber));
695 
696  btree_xlog_updates(page, updatedoffsets, updates, xlrec->nupdated);
697  }
698 
699  if (xlrec->ndeleted > 0)
700  PageIndexMultiDelete(page, (OffsetNumber *) ptr, xlrec->ndeleted);
701 
702  /* Mark the page as not containing any LP_DEAD items */
703  opaque = (BTPageOpaque) PageGetSpecialPointer(page);
704  opaque->btpo_flags &= ~BTP_HAS_GARBAGE;
705 
706  PageSetLSN(page, lsn);
707  MarkBufferDirty(buffer);
708  }
709  if (BufferIsValid(buffer))
710  UnlockReleaseBuffer(buffer);
711 }
uint16 ndeleted
Definition: nbtxlog.h:236
TransactionId latestRemovedXid
Definition: nbtxlog.h:235
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
uint16 nupdated
Definition: nbtxlog.h:237
#define InHotStandby
Definition: xlog.h:74
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
static void btree_xlog_updates(Page page, OffsetNumber *updatedoffsets, xl_btree_update *updates, int nupdated)
Definition: nbtxlog.c:560
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1491
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:1154
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
Definition: standby.c:443
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define BTP_HAS_GARBAGE
Definition: nbtree.h:80
Pointer Page
Definition: bufpage.h:78

◆ btree_xlog_insert()

static void btree_xlog_insert ( bool  isleaf,
bool  ismeta,
bool  posting,
XLogReaderState record 
)
static

Definition at line 163 of file nbtxlog.c.

References _bt_clear_incomplete_split(), _bt_restore_meta(), _bt_swap_posting(), Assert, BLK_NEEDS_REDO, BufferGetPage, BufferIsValid, CopyIndexTuple(), elog, XLogReaderState::EndRecPtr, IndexTupleSize, InvalidOffsetNumber, MarkBufferDirty(), MAXALIGN, xl_btree_insert::offnum, OffsetNumberPrev, PageAddItem, PageGetItem, PageGetItemId, PageSetLSN, PANIC, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by btree_redo().

165 {
166  XLogRecPtr lsn = record->EndRecPtr;
167  xl_btree_insert *xlrec = (xl_btree_insert *) XLogRecGetData(record);
168  Buffer buffer;
169  Page page;
170 
171  /*
172  * Insertion to an internal page finishes an incomplete split at the child
173  * level. Clear the incomplete-split flag in the child. Note: during
174  * normal operation, the child and parent pages are locked at the same
175  * time (the locks are coupled), so that clearing the flag and inserting
176  * the downlink appear atomic to other backends. We don't bother with
177  * that during replay, because readers don't care about the
178  * incomplete-split flag and there cannot be updates happening.
179  */
180  if (!isleaf)
181  _bt_clear_incomplete_split(record, 1);
182  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
183  {
184  Size datalen;
185  char *datapos = XLogRecGetBlockData(record, 0, &datalen);
186 
187  page = BufferGetPage(buffer);
188 
189  if (!posting)
190  {
191  /* Simple retail insertion */
192  if (PageAddItem(page, (Item) datapos, datalen, xlrec->offnum,
193  false, false) == InvalidOffsetNumber)
194  elog(PANIC, "failed to add new item");
195  }
196  else
197  {
198  ItemId itemid;
199  IndexTuple oposting,
200  newitem,
201  nposting;
202  uint16 postingoff;
203 
204  /*
205  * A posting list split occurred during leaf page insertion. WAL
206  * record data will start with an offset number representing the
207  * point in an existing posting list that a split occurs at.
208  *
209  * Use _bt_swap_posting() to repeat posting list split steps from
210  * primary. Note that newitem from WAL record is 'orignewitem',
211  * not the final version of newitem that is actually inserted on
212  * page.
213  */
214  postingoff = *((uint16 *) datapos);
215  datapos += sizeof(uint16);
216  datalen -= sizeof(uint16);
217 
218  itemid = PageGetItemId(page, OffsetNumberPrev(xlrec->offnum));
219  oposting = (IndexTuple) PageGetItem(page, itemid);
220 
221  /* Use mutable, aligned newitem copy in _bt_swap_posting() */
222  Assert(isleaf && postingoff > 0);
223  newitem = CopyIndexTuple((IndexTuple) datapos);
224  nposting = _bt_swap_posting(newitem, oposting, postingoff);
225 
226  /* Replace existing posting list with post-split version */
227  memcpy(oposting, nposting, MAXALIGN(IndexTupleSize(nposting)));
228 
229  /* Insert "final" new item (not orignewitem from WAL stream) */
230  Assert(IndexTupleSize(newitem) == datalen);
231  if (PageAddItem(page, (Item) newitem, datalen, xlrec->offnum,
232  false, false) == InvalidOffsetNumber)
233  elog(PANIC, "failed to add posting split new item");
234  }
235 
236  PageSetLSN(page, lsn);
237  MarkBufferDirty(buffer);
238  }
239  if (BufferIsValid(buffer))
240  UnlockReleaseBuffer(buffer);
241 
242  /*
243  * Note: in normal operation, we'd update the metapage while still holding
244  * lock on the page we inserted into. But during replay it's not
245  * necessary to hold that lock, since no other index updates can be
246  * happening concurrently, and readers will cope fine with following an
247  * obsolete link from the metapage.
248  */
249  if (ismeta)
250  _bt_restore_meta(record, 2);
251 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
#define PANIC
Definition: elog.h:50
IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting, int postingoff)
Definition: nbtdedup.c:1017
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
unsigned short uint16
Definition: c.h:440
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
IndexTuple CopyIndexTuple(IndexTuple source)
Definition: indextuple.c:537
static void _bt_clear_incomplete_split(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:142
IndexTupleData * IndexTuple
Definition: itup.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
OffsetNumber offnum
Definition: nbtxlog.h:81
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
size_t Size
Definition: c.h:540
#define OffsetNumberPrev(offsetNumber)
Definition: off.h:54
#define MAXALIGN(LEN)
Definition: c.h:757
#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
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ btree_xlog_mark_page_halfdead()

static void btree_xlog_mark_page_halfdead ( uint8  info,
XLogReaderState record 
)
static

Definition at line 714 of file nbtxlog.c.

References _bt_pageinit(), BLK_NEEDS_REDO, BTP_HALF_DEAD, BTP_LEAF, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_level, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, BTreeTupleGetDownLink(), BTreeTupleSetDownLink(), BTreeTupleSetTopParent(), BufferGetPage, BufferGetPageSize, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, InvalidOffsetNumber, xl_btree_mark_page_halfdead::leftblk, MarkBufferDirty(), MemSet, OffsetNumberNext, P_HIKEY, PageAddItem, PageGetItem, PageGetItemId, PageGetSpecialPointer, PageIndexTupleDelete(), PageSetLSN, xl_btree_mark_page_halfdead::poffset, xl_btree_mark_page_halfdead::rightblk, IndexTupleData::t_info, xl_btree_mark_page_halfdead::topparent, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), and XLogRecGetData.

Referenced by btree_redo().

715 {
716  XLogRecPtr lsn = record->EndRecPtr;
718  Buffer buffer;
719  Page page;
720  BTPageOpaque pageop;
721  IndexTupleData trunctuple;
722 
723  /*
724  * In normal operation, we would lock all the pages this WAL record
725  * touches before changing any of them. In WAL replay, it should be okay
726  * to lock just one page at a time, since no concurrent index updates can
727  * be happening, and readers should not care whether they arrive at the
728  * target page or not (since it's surely empty).
729  */
730 
731  /* to-be-deleted subtree's parent page */
732  if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
733  {
734  OffsetNumber poffset;
735  ItemId itemid;
736  IndexTuple itup;
737  OffsetNumber nextoffset;
738  BlockNumber rightsib;
739 
740  page = (Page) BufferGetPage(buffer);
741  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
742 
743  poffset = xlrec->poffset;
744 
745  nextoffset = OffsetNumberNext(poffset);
746  itemid = PageGetItemId(page, nextoffset);
747  itup = (IndexTuple) PageGetItem(page, itemid);
748  rightsib = BTreeTupleGetDownLink(itup);
749 
750  itemid = PageGetItemId(page, poffset);
751  itup = (IndexTuple) PageGetItem(page, itemid);
752  BTreeTupleSetDownLink(itup, rightsib);
753  nextoffset = OffsetNumberNext(poffset);
754  PageIndexTupleDelete(page, nextoffset);
755 
756  PageSetLSN(page, lsn);
757  MarkBufferDirty(buffer);
758  }
759 
760  /*
761  * Don't need to couple cross-level locks in REDO routines, so release
762  * lock on internal page immediately
763  */
764  if (BufferIsValid(buffer))
765  UnlockReleaseBuffer(buffer);
766 
767  /* Rewrite the leaf page as a halfdead page */
768  buffer = XLogInitBufferForRedo(record, 0);
769  page = (Page) BufferGetPage(buffer);
770 
771  _bt_pageinit(page, BufferGetPageSize(buffer));
772  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
773 
774  pageop->btpo_prev = xlrec->leftblk;
775  pageop->btpo_next = xlrec->rightblk;
776  pageop->btpo_level = 0;
777  pageop->btpo_flags = BTP_HALF_DEAD | BTP_LEAF;
778  pageop->btpo_cycleid = 0;
779 
780  /*
781  * Construct a dummy high key item that points to top parent page (value
782  * is InvalidBlockNumber when the top parent page is the leaf page itself)
783  */
784  MemSet(&trunctuple, 0, sizeof(IndexTupleData));
785  trunctuple.t_info = sizeof(IndexTupleData);
786  BTreeTupleSetTopParent(&trunctuple, xlrec->topparent);
787 
788  if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY,
789  false, false) == InvalidOffsetNumber)
790  elog(ERROR, "could not add dummy high key to half-dead page");
791 
792  PageSetLSN(page, lsn);
793  MarkBufferDirty(buffer);
794  UnlockReleaseBuffer(buffer);
795 }
BlockNumber btpo_next
Definition: nbtree.h:65
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:1045
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
#define BTP_LEAF
Definition: nbtree.h:74
#define BTP_HALF_DEAD
Definition: nbtree.h:78
Pointer Item
Definition: item.h:17
static BlockNumber BTreeTupleGetDownLink(IndexTuple pivot)
Definition: nbtree.h:549
#define MemSet(start, val, len)
Definition: c.h:1008
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
#define ERROR
Definition: elog.h:46
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:304
BTCycleId btpo_cycleid
Definition: nbtree.h:68
BlockNumber btpo_prev
Definition: nbtree.h:64
uint32 btpo_level
Definition: nbtree.h:66
IndexTupleData * IndexTuple
Definition: itup.h:53
static void BTreeTupleSetDownLink(IndexTuple pivot, BlockNumber blkno)
Definition: nbtree.h:555
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
struct IndexTupleData IndexTupleData
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define P_HIKEY
Definition: nbtree.h:367
#define elog(elevel,...)
Definition: elog.h:232
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:1142
unsigned short t_info
Definition: itup.h:49
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
static void BTreeTupleSetTopParent(IndexTuple leafhikey, BlockNumber blkno)
Definition: nbtree.h:619
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78

◆ btree_xlog_newroot()

static void btree_xlog_newroot ( XLogReaderState record)
static

Definition at line 938 of file nbtxlog.c.

References _bt_clear_incomplete_split(), _bt_pageinit(), _bt_restore_meta(), _bt_restore_page(), BTP_LEAF, BTP_ROOT, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_level, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, BufferGetPage, BufferGetPageSize, XLogReaderState::EndRecPtr, xl_btree_newroot::level, MarkBufferDirty(), P_NONE, PageGetSpecialPointer, PageSetLSN, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by btree_redo().

939 {
940  XLogRecPtr lsn = record->EndRecPtr;
941  xl_btree_newroot *xlrec = (xl_btree_newroot *) XLogRecGetData(record);
942  Buffer buffer;
943  Page page;
944  BTPageOpaque pageop;
945  char *ptr;
946  Size len;
947 
948  buffer = XLogInitBufferForRedo(record, 0);
949  page = (Page) BufferGetPage(buffer);
950 
951  _bt_pageinit(page, BufferGetPageSize(buffer));
952  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
953 
954  pageop->btpo_flags = BTP_ROOT;
955  pageop->btpo_prev = pageop->btpo_next = P_NONE;
956  pageop->btpo_level = xlrec->level;
957  if (xlrec->level == 0)
958  pageop->btpo_flags |= BTP_LEAF;
959  pageop->btpo_cycleid = 0;
960 
961  if (xlrec->level > 0)
962  {
963  ptr = XLogRecGetBlockData(record, 0, &len);
964  _bt_restore_page(page, ptr, len);
965 
966  /* Clear the incomplete-split flag in left child */
967  _bt_clear_incomplete_split(record, 1);
968  }
969 
970  PageSetLSN(page, lsn);
971  MarkBufferDirty(buffer);
972  UnlockReleaseBuffer(buffer);
973 
974  _bt_restore_meta(record, 2);
975 }
#define BTP_ROOT
Definition: nbtree.h:75
BlockNumber btpo_next
Definition: nbtree.h:65
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
#define BTP_LEAF
Definition: nbtree.h:74
#define P_NONE
Definition: nbtree.h:211
uint32 level
Definition: nbtxlog.h:335
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:304
BTCycleId btpo_cycleid
Definition: nbtree.h:68
BlockNumber btpo_prev
Definition: nbtree.h:64
static void _bt_clear_incomplete_split(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:142
uint32 btpo_level
Definition: nbtree.h:66
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
static void _bt_restore_page(Page page, char *from, int len)
Definition: nbtxlog.c:38
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
uint64 XLogRecPtr
Definition: xlogdefs.h:21
size_t Size
Definition: c.h:540
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:1142
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:78

◆ btree_xlog_reuse_page()

static void btree_xlog_reuse_page ( XLogReaderState record)
static

Definition at line 1004 of file nbtxlog.c.

References InHotStandby, xl_btree_reuse_page::latestRemovedFullXid, xl_btree_reuse_page::node, ResolveRecoveryConflictWithSnapshotFullXid(), and XLogRecGetData.

Referenced by btree_redo().

1005 {
1007 
1008  if (InHotStandby)
1010  xlrec->node);
1011 }
FullTransactionId latestRemovedFullXid
Definition: nbtxlog.h:190
RelFileNode node
Definition: nbtxlog.h:188
#define InHotStandby
Definition: xlog.h:74
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void ResolveRecoveryConflictWithSnapshotFullXid(FullTransactionId latestRemovedFullXid, RelFileNode node)
Definition: standby.c:475

◆ btree_xlog_split()

static void btree_xlog_split ( bool  newitemonleft,
XLogReaderState record 
)
static

Definition at line 254 of file nbtxlog.c.

References _bt_clear_incomplete_split(), _bt_pageinit(), _bt_restore_page(), _bt_swap_posting(), Assert, BLK_NEEDS_REDO, BTP_INCOMPLETE_SPLIT, BTP_LEAF, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_level, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, buf, BufferGetPage, BufferGetPageSize, BufferIsValid, CopyIndexTuple(), elog, XLogReaderState::EndRecPtr, ERROR, xl_btree_split::firstrightoff, IndexTupleSize, InvalidOffsetNumber, ItemIdGetLength, xl_btree_split::level, MarkBufferDirty(), MAXALIGN, xl_btree_split::newitemoff, OffsetNumberNext, OffsetNumberPrev, P_FIRSTDATAKEY, P_HIKEY, P_NONE, PageAddItem, PageGetItem, PageGetItemId, PageGetSpecialPointer, PageGetTempPageCopySpecial(), PageRestoreTempPage(), PageSetLSN, xl_btree_split::postingoff, UnlockReleaseBuffer(), XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetBlockData(), XLogRecGetBlockTag(), and XLogRecGetData.

Referenced by btree_redo().

255 {
256  XLogRecPtr lsn = record->EndRecPtr;
257  xl_btree_split *xlrec = (xl_btree_split *) XLogRecGetData(record);
258  bool isleaf = (xlrec->level == 0);
259  Buffer buf;
260  Buffer rbuf;
261  Page rpage;
262  BTPageOpaque ropaque;
263  char *datapos;
264  Size datalen;
265  BlockNumber origpagenumber;
266  BlockNumber rightpagenumber;
267  BlockNumber spagenumber;
268 
269  XLogRecGetBlockTag(record, 0, NULL, NULL, &origpagenumber);
270  XLogRecGetBlockTag(record, 1, NULL, NULL, &rightpagenumber);
271  if (!XLogRecGetBlockTag(record, 2, NULL, NULL, &spagenumber))
272  spagenumber = P_NONE;
273 
274  /*
275  * Clear the incomplete split flag on the appropriate child page one level
276  * down when origpage/buf is an internal page (there must have been
277  * cascading page splits during original execution in the event of an
278  * internal page split). This is like the corresponding btree_xlog_insert
279  * call for internal pages. We're not clearing the incomplete split flag
280  * for the current page split here (you can think of this as part of the
281  * insert of newitem that the page split action needs to perform in
282  * passing).
283  *
284  * Like in btree_xlog_insert, this can be done before locking other pages.
285  * We never need to couple cross-level locks in REDO routines.
286  */
287  if (!isleaf)
288  _bt_clear_incomplete_split(record, 3);
289 
290  /* Reconstruct right (new) sibling page from scratch */
291  rbuf = XLogInitBufferForRedo(record, 1);
292  datapos = XLogRecGetBlockData(record, 1, &datalen);
293  rpage = (Page) BufferGetPage(rbuf);
294 
295  _bt_pageinit(rpage, BufferGetPageSize(rbuf));
296  ropaque = (BTPageOpaque) PageGetSpecialPointer(rpage);
297 
298  ropaque->btpo_prev = origpagenumber;
299  ropaque->btpo_next = spagenumber;
300  ropaque->btpo_level = xlrec->level;
301  ropaque->btpo_flags = isleaf ? BTP_LEAF : 0;
302  ropaque->btpo_cycleid = 0;
303 
304  _bt_restore_page(rpage, datapos, datalen);
305 
306  PageSetLSN(rpage, lsn);
307  MarkBufferDirty(rbuf);
308 
309  /* Now reconstruct original page (left half of split) */
310  if (XLogReadBufferForRedo(record, 0, &buf) == BLK_NEEDS_REDO)
311  {
312  /*
313  * To retain the same physical order of the tuples that they had, we
314  * initialize a temporary empty page for the left page and add all the
315  * items to that in item number order. This mirrors how _bt_split()
316  * works. Retaining the same physical order makes WAL consistency
317  * checking possible. See also _bt_restore_page(), which does the
318  * same for the right page.
319  */
320  Page origpage = (Page) BufferGetPage(buf);
321  BTPageOpaque oopaque = (BTPageOpaque) PageGetSpecialPointer(origpage);
322  OffsetNumber off;
323  IndexTuple newitem = NULL,
324  left_hikey = NULL,
325  nposting = NULL;
326  Size newitemsz = 0,
327  left_hikeysz = 0;
328  Page leftpage;
329  OffsetNumber leftoff,
330  replacepostingoff = InvalidOffsetNumber;
331 
332  datapos = XLogRecGetBlockData(record, 0, &datalen);
333 
334  if (newitemonleft || xlrec->postingoff != 0)
335  {
336  newitem = (IndexTuple) datapos;
337  newitemsz = MAXALIGN(IndexTupleSize(newitem));
338  datapos += newitemsz;
339  datalen -= newitemsz;
340 
341  if (xlrec->postingoff != 0)
342  {
343  ItemId itemid;
344  IndexTuple oposting;
345 
346  /* Posting list must be at offset number before new item's */
347  replacepostingoff = OffsetNumberPrev(xlrec->newitemoff);
348 
349  /* Use mutable, aligned newitem copy in _bt_swap_posting() */
350  newitem = CopyIndexTuple(newitem);
351  itemid = PageGetItemId(origpage, replacepostingoff);
352  oposting = (IndexTuple) PageGetItem(origpage, itemid);
353  nposting = _bt_swap_posting(newitem, oposting,
354  xlrec->postingoff);
355  }
356  }
357 
358  /*
359  * Extract left hikey and its size. We assume that 16-bit alignment
360  * is enough to apply IndexTupleSize (since it's fetching from a
361  * uint16 field).
362  */
363  left_hikey = (IndexTuple) datapos;
364  left_hikeysz = MAXALIGN(IndexTupleSize(left_hikey));
365  datapos += left_hikeysz;
366  datalen -= left_hikeysz;
367 
368  Assert(datalen == 0);
369 
370  leftpage = PageGetTempPageCopySpecial(origpage);
371 
372  /* Add high key tuple from WAL record to temp page */
373  leftoff = P_HIKEY;
374  if (PageAddItem(leftpage, (Item) left_hikey, left_hikeysz, P_HIKEY,
375  false, false) == InvalidOffsetNumber)
376  elog(ERROR, "failed to add high key to left page after split");
377  leftoff = OffsetNumberNext(leftoff);
378 
379  for (off = P_FIRSTDATAKEY(oopaque); off < xlrec->firstrightoff; off++)
380  {
381  ItemId itemid;
382  Size itemsz;
383  IndexTuple item;
384 
385  /* Add replacement posting list when required */
386  if (off == replacepostingoff)
387  {
388  Assert(newitemonleft ||
389  xlrec->firstrightoff == xlrec->newitemoff);
390  if (PageAddItem(leftpage, (Item) nposting,
391  MAXALIGN(IndexTupleSize(nposting)), leftoff,
392  false, false) == InvalidOffsetNumber)
393  elog(ERROR, "failed to add new posting list item to left page after split");
394  leftoff = OffsetNumberNext(leftoff);
395  continue; /* don't insert oposting */
396  }
397 
398  /* add the new item if it was inserted on left page */
399  else if (newitemonleft && off == xlrec->newitemoff)
400  {
401  if (PageAddItem(leftpage, (Item) newitem, newitemsz, leftoff,
402  false, false) == InvalidOffsetNumber)
403  elog(ERROR, "failed to add new item to left page after split");
404  leftoff = OffsetNumberNext(leftoff);
405  }
406 
407  itemid = PageGetItemId(origpage, off);
408  itemsz = ItemIdGetLength(itemid);
409  item = (IndexTuple) PageGetItem(origpage, itemid);
410  if (PageAddItem(leftpage, (Item) item, itemsz, leftoff,
411  false, false) == InvalidOffsetNumber)
412  elog(ERROR, "failed to add old item to left page after split");
413  leftoff = OffsetNumberNext(leftoff);
414  }
415 
416  /* cope with possibility that newitem goes at the end */
417  if (newitemonleft && off == xlrec->newitemoff)
418  {
419  if (PageAddItem(leftpage, (Item) newitem, newitemsz, leftoff,
420  false, false) == InvalidOffsetNumber)
421  elog(ERROR, "failed to add new item to left page after split");
422  leftoff = OffsetNumberNext(leftoff);
423  }
424 
425  PageRestoreTempPage(leftpage, origpage);
426 
427  /* Fix opaque fields */
428  oopaque->btpo_flags = BTP_INCOMPLETE_SPLIT;
429  if (isleaf)
430  oopaque->btpo_flags |= BTP_LEAF;
431  oopaque->btpo_next = rightpagenumber;
432  oopaque->btpo_cycleid = 0;
433 
434  PageSetLSN(origpage, lsn);
435  MarkBufferDirty(buf);
436  }
437 
438  /* Fix left-link of the page to the right of the new right sibling */
439  if (spagenumber != P_NONE)
440  {
441  Buffer sbuf;
442 
443  if (XLogReadBufferForRedo(record, 2, &sbuf) == BLK_NEEDS_REDO)
444  {
445  Page spage = (Page) BufferGetPage(sbuf);
447 
448  spageop->btpo_prev = rightpagenumber;
449 
450  PageSetLSN(spage, lsn);
451  MarkBufferDirty(sbuf);
452  }
453  if (BufferIsValid(sbuf))
454  UnlockReleaseBuffer(sbuf);
455  }
456 
457  /*
458  * Finally, release the remaining buffers. sbuf, rbuf, and buf must be
459  * released together, so that readers cannot observe inconsistencies.
460  */
461  UnlockReleaseBuffer(rbuf);
462  if (BufferIsValid(buf))
463  UnlockReleaseBuffer(buf);
464 }
BlockNumber btpo_next
Definition: nbtree.h:65
void PageRestoreTempPage(Page tempPage, Page oldPage)
Definition: bufpage.c:424
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:369
#define BTP_LEAF
Definition: nbtree.h:74
Pointer Item
Definition: item.h:17
#define P_NONE
Definition: nbtree.h:211
#define BTP_INCOMPLETE_SPLIT
Definition: nbtree.h:81
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting, int postingoff)
Definition: nbtdedup.c:1017
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
Page PageGetTempPageCopySpecial(Page page)
Definition: bufpage.c:402
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
#define ERROR
Definition: elog.h:46
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:304
OffsetNumber newitemoff
Definition: nbtxlog.h:157
BTCycleId btpo_cycleid
Definition: nbtree.h:68
BlockNumber btpo_prev
Definition: nbtree.h:64
IndexTuple CopyIndexTuple(IndexTuple source)
Definition: indextuple.c:537
static void _bt_clear_incomplete_split(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:142
uint32 btpo_level
Definition: nbtree.h:66
static char * buf
Definition: pg_test_fsync.c:68
IndexTupleData * IndexTuple
Definition: itup.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1491
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
uint32 level
Definition: nbtxlog.h:155
static void _bt_restore_page(Page page, char *from, int len)
Definition: nbtxlog.c:38
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
size_t Size
Definition: c.h:540
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define OffsetNumberPrev(offsetNumber)
Definition: off.h:54
#define MAXALIGN(LEN)
Definition: c.h:757
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define P_HIKEY
Definition: nbtree.h:367
#define elog(elevel,...)
Definition: elog.h:232
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:1142
uint16 postingoff
Definition: nbtxlog.h:158
uint16 btpo_flags
Definition: nbtree.h:67
OffsetNumber firstrightoff
Definition: nbtxlog.h:156
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ btree_xlog_startup()

void btree_xlog_startup ( void  )

Definition at line 1073 of file nbtxlog.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, and CurrentMemoryContext.

1074 {
1076  "Btree recovery temporary context",
1078 }
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static MemoryContext opCtx
Definition: nbtxlog.c:27

◆ btree_xlog_unlink_page()

static void btree_xlog_unlink_page ( uint8  info,
XLogReaderState record 
)
static

Definition at line 799 of file nbtxlog.c.

References _bt_pageinit(), _bt_restore_meta(), Assert, BLK_NEEDS_REDO, BlockNumberIsValid, BTP_HALF_DEAD, BTP_LEAF, BTPageSetDeleted(), BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_level, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, BTreeTupleSetTopParent(), BufferGetPage, BufferGetPageSize, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, InvalidBuffer, InvalidOffsetNumber, xl_btree_unlink_page::leafleftsib, xl_btree_unlink_page::leafrightsib, xl_btree_unlink_page::leaftopparent, xl_btree_unlink_page::leftsib, xl_btree_unlink_page::level, MarkBufferDirty(), MemSet, P_HIKEY, P_NONE, PageAddItem, PageGetSpecialPointer, PageSetLSN, xl_btree_unlink_page::rightsib, xl_btree_unlink_page::safexid, IndexTupleData::t_info, UnlockReleaseBuffer(), XLOG_BTREE_UNLINK_PAGE_META, XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by btree_redo().

800 {
801  XLogRecPtr lsn = record->EndRecPtr;
803  BlockNumber leftsib;
804  BlockNumber rightsib;
805  uint32 level;
806  bool isleaf;
807  FullTransactionId safexid;
808  Buffer leftbuf;
809  Buffer target;
810  Buffer rightbuf;
811  Page page;
812  BTPageOpaque pageop;
813 
814  leftsib = xlrec->leftsib;
815  rightsib = xlrec->rightsib;
816  level = xlrec->level;
817  isleaf = (level == 0);
818  safexid = xlrec->safexid;
819 
820  /* No leaftopparent for level 0 (leaf page) or level 1 target */
821  Assert(!BlockNumberIsValid(xlrec->leaftopparent) || level > 1);
822 
823  /*
824  * In normal operation, we would lock all the pages this WAL record
825  * touches before changing any of them. In WAL replay, we at least lock
826  * the pages in the same standard left-to-right order (leftsib, target,
827  * rightsib), and don't release the sibling locks until the target is
828  * marked deleted.
829  */
830 
831  /* Fix right-link of left sibling, if any */
832  if (leftsib != P_NONE)
833  {
834  if (XLogReadBufferForRedo(record, 1, &leftbuf) == BLK_NEEDS_REDO)
835  {
836  page = (Page) BufferGetPage(leftbuf);
837  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
838  pageop->btpo_next = rightsib;
839 
840  PageSetLSN(page, lsn);
841  MarkBufferDirty(leftbuf);
842  }
843  }
844  else
845  leftbuf = InvalidBuffer;
846 
847  /* Rewrite target page as empty deleted page */
848  target = XLogInitBufferForRedo(record, 0);
849  page = (Page) BufferGetPage(target);
850 
851  _bt_pageinit(page, BufferGetPageSize(target));
852  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
853 
854  pageop->btpo_prev = leftsib;
855  pageop->btpo_next = rightsib;
856  pageop->btpo_level = level;
857  BTPageSetDeleted(page, safexid);
858  if (isleaf)
859  pageop->btpo_flags |= BTP_LEAF;
860  pageop->btpo_cycleid = 0;
861 
862  PageSetLSN(page, lsn);
863  MarkBufferDirty(target);
864 
865  /* Fix left-link of right sibling */
866  if (XLogReadBufferForRedo(record, 2, &rightbuf) == BLK_NEEDS_REDO)
867  {
868  page = (Page) BufferGetPage(rightbuf);
869  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
870  pageop->btpo_prev = leftsib;
871 
872  PageSetLSN(page, lsn);
873  MarkBufferDirty(rightbuf);
874  }
875 
876  /* Release siblings */
877  if (BufferIsValid(leftbuf))
878  UnlockReleaseBuffer(leftbuf);
879  if (BufferIsValid(rightbuf))
880  UnlockReleaseBuffer(rightbuf);
881 
882  /* Release target */
883  UnlockReleaseBuffer(target);
884 
885  /*
886  * If we deleted a parent of the targeted leaf page, instead of the leaf
887  * itself, update the leaf to point to the next remaining child in the
888  * to-be-deleted subtree
889  */
890  if (XLogRecHasBlockRef(record, 3))
891  {
892  /*
893  * There is no real data on the page, so we just re-create it from
894  * scratch using the information from the WAL record.
895  *
896  * Note that we don't end up here when the target page is also the
897  * leafbuf page. There is no need to add a dummy hikey item with a
898  * top parent link when deleting leafbuf because it's the last page
899  * we'll delete in the subtree undergoing deletion.
900  */
901  Buffer leafbuf;
902  IndexTupleData trunctuple;
903 
904  Assert(!isleaf);
905 
906  leafbuf = XLogInitBufferForRedo(record, 3);
907  page = (Page) BufferGetPage(leafbuf);
908 
909  _bt_pageinit(page, BufferGetPageSize(leafbuf));
910  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
911 
912  pageop->btpo_flags = BTP_HALF_DEAD | BTP_LEAF;
913  pageop->btpo_prev = xlrec->leafleftsib;
914  pageop->btpo_next = xlrec->leafrightsib;
915  pageop->btpo_level = 0;
916  pageop->btpo_cycleid = 0;
917 
918  /* Add a dummy hikey item */
919  MemSet(&trunctuple, 0, sizeof(IndexTupleData));
920  trunctuple.t_info = sizeof(IndexTupleData);
921  BTreeTupleSetTopParent(&trunctuple, xlrec->leaftopparent);
922 
923  if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY,
924  false, false) == InvalidOffsetNumber)
925  elog(ERROR, "could not add dummy high key to half-dead page");
926 
927  PageSetLSN(page, lsn);
928  MarkBufferDirty(leafbuf);
929  UnlockReleaseBuffer(leafbuf);
930  }
931 
932  /* Update metapage if needed */
933  if (info == XLOG_BTREE_UNLINK_PAGE_META)
934  _bt_restore_meta(record, 4);
935 }
BlockNumber btpo_next
Definition: nbtree.h:65
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
#define BTP_LEAF
Definition: nbtree.h:74
#define BTP_HALF_DEAD
Definition: nbtree.h:78
Pointer Item
Definition: item.h:17
#define P_NONE
Definition: nbtree.h:211
#define InvalidBuffer
Definition: buf.h:25
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:313
#define MemSet(start, val, len)
Definition: c.h:1008
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
#define ERROR
Definition: elog.h:46
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:304
BTCycleId btpo_cycleid
Definition: nbtree.h:68
BlockNumber btpo_prev
Definition: nbtree.h:64
uint32 btpo_level
Definition: nbtree.h:66
unsigned int uint32
Definition: c.h:441
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
struct IndexTupleData IndexTupleData
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
#define InvalidOffsetNumber
Definition: off.h:26
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:292
static void BTPageSetDeleted(Page page, FullTransactionId safexid)
Definition: nbtree.h:238
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
#define P_HIKEY
Definition: nbtree.h:367
#define elog(elevel,...)
Definition: elog.h:232
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:1142
#define XLOG_BTREE_UNLINK_PAGE_META
Definition: nbtxlog.h:36
unsigned short t_info
Definition: itup.h:49
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
static void BTreeTupleSetTopParent(IndexTuple leafhikey, BlockNumber blkno)
Definition: nbtree.h:619
Pointer Page
Definition: bufpage.h:78

◆ btree_xlog_updates()

static void btree_xlog_updates ( Page  page,
OffsetNumber updatedoffsets,
xl_btree_update updates,
int  nupdated 
)
static

Definition at line 560 of file nbtxlog.c.

References _bt_update_posting(), BTVacuumPostingData::deletetids, elog, i, IndexTupleSize, BTVacuumPostingData::itup, MAXALIGN, xl_btree_update::ndeletedtids, BTVacuumPostingData::ndeletedtids, offsetof, PageGetItem, PageGetItemId, PageIndexTupleOverwrite(), palloc(), PANIC, pfree(), SizeOfBtreeUpdate, and BTVacuumPostingData::updatedoffset.

Referenced by btree_xlog_delete(), and btree_xlog_vacuum().

562 {
563  BTVacuumPosting vacposting;
564  IndexTuple origtuple;
565  ItemId itemid;
566  Size itemsz;
567 
568  for (int i = 0; i < nupdated; i++)
569  {
570  itemid = PageGetItemId(page, updatedoffsets[i]);
571  origtuple = (IndexTuple) PageGetItem(page, itemid);
572 
573  vacposting = palloc(offsetof(BTVacuumPostingData, deletetids) +
574  updates->ndeletedtids * sizeof(uint16));
575  vacposting->updatedoffset = updatedoffsets[i];
576  vacposting->itup = origtuple;
577  vacposting->ndeletedtids = updates->ndeletedtids;
578  memcpy(vacposting->deletetids,
579  (char *) updates + SizeOfBtreeUpdate,
580  updates->ndeletedtids * sizeof(uint16));
581 
582  _bt_update_posting(vacposting);
583 
584  /* Overwrite updated version of tuple */
585  itemsz = MAXALIGN(IndexTupleSize(vacposting->itup));
586  if (!PageIndexTupleOverwrite(page, updatedoffsets[i],
587  (Item) vacposting->itup, itemsz))
588  elog(PANIC, "failed to update partially dead item");
589 
590  pfree(vacposting->itup);
591  pfree(vacposting);
592 
593  /* advance to next xl_btree_update from array */
594  updates = (xl_btree_update *)
595  ((char *) updates + SizeOfBtreeUpdate +
596  updates->ndeletedtids * sizeof(uint16));
597  }
598 }
uint16 ndeletedtids
Definition: nbtree.h:908
void _bt_update_posting(BTVacuumPosting vacposting)
Definition: nbtdedup.c:919
#define SizeOfBtreeUpdate
Definition: nbtxlog.h:259
OffsetNumber updatedoffset
Definition: nbtree.h:905
IndexTuple itup
Definition: nbtree.h:904
Pointer Item
Definition: item.h:17
#define PANIC
Definition: elog.h:50
unsigned short uint16
Definition: c.h:440
void pfree(void *pointer)
Definition: mcxt.c:1169
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1398
IndexTupleData * IndexTuple
Definition: itup.h:53
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
uint16 deletetids[FLEXIBLE_ARRAY_MEMBER]
Definition: nbtree.h:909
size_t Size
Definition: c.h:540
#define MAXALIGN(LEN)
Definition: c.h:757
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
int i
#define offsetof(type, field)
Definition: c.h:727
uint16 ndeletedtids
Definition: nbtxlog.h:254
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ btree_xlog_vacuum()

static void btree_xlog_vacuum ( XLogReaderState record)
static

Definition at line 601 of file nbtxlog.c.

References BLK_NEEDS_REDO, BTP_HAS_GARBAGE, BTPageOpaqueData::btpo_flags, btree_xlog_updates(), BufferGetPage, BufferIsValid, XLogReaderState::EndRecPtr, MarkBufferDirty(), xl_btree_vacuum::ndeleted, xl_btree_vacuum::nupdated, PageGetSpecialPointer, PageIndexMultiDelete(), PageSetLSN, RBM_NORMAL, UnlockReleaseBuffer(), XLogReadBufferForRedoExtended(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by btree_redo().

602 {
603  XLogRecPtr lsn = record->EndRecPtr;
604  xl_btree_vacuum *xlrec = (xl_btree_vacuum *) XLogRecGetData(record);
605  Buffer buffer;
606  Page page;
607  BTPageOpaque opaque;
608 
609  /*
610  * We need to take a cleanup lock here, just like btvacuumpage(). However,
611  * it isn't necessary to exhaustively get a cleanup lock on every block in
612  * the index during recovery (just getting a cleanup lock on pages with
613  * items to kill suffices). See nbtree/README for details.
614  */
615  if (XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &buffer)
616  == BLK_NEEDS_REDO)
617  {
618  char *ptr = XLogRecGetBlockData(record, 0, NULL);
619 
620  page = (Page) BufferGetPage(buffer);
621 
622  if (xlrec->nupdated > 0)
623  {
624  OffsetNumber *updatedoffsets;
625  xl_btree_update *updates;
626 
627  updatedoffsets = (OffsetNumber *)
628  (ptr + xlrec->ndeleted * sizeof(OffsetNumber));
629  updates = (xl_btree_update *) ((char *) updatedoffsets +
630  xlrec->nupdated *
631  sizeof(OffsetNumber));
632 
633  btree_xlog_updates(page, updatedoffsets, updates, xlrec->nupdated);
634  }
635 
636  if (xlrec->ndeleted > 0)
637  PageIndexMultiDelete(page, (OffsetNumber *) ptr, xlrec->ndeleted);
638 
639  /*
640  * Mark the page as not containing any LP_DEAD items --- see comments
641  * in _bt_delitems_vacuum().
642  */
643  opaque = (BTPageOpaque) PageGetSpecialPointer(page);
644  opaque->btpo_flags &= ~BTP_HAS_GARBAGE;
645 
646  PageSetLSN(page, lsn);
647  MarkBufferDirty(buffer);
648  }
649  if (BufferIsValid(buffer))
650  UnlockReleaseBuffer(buffer);
651 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1562
uint16 nupdated
Definition: nbtxlog.h:224
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:71
XLogRecPtr EndRecPtr
Definition: xlogreader.h:176
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:310
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3807
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
uint16 ndeleted
Definition: nbtxlog.h:223
static void btree_xlog_updates(Page page, OffsetNumber *updatedoffsets, xl_btree_update *updates, int nupdated)
Definition: nbtxlog.c:560
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1515
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:1154
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:123
XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)
Definition: xlogutils.c:329
uint16 btpo_flags
Definition: nbtree.h:67
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define BTP_HAS_GARBAGE
Definition: nbtree.h:80
Pointer Page
Definition: bufpage.h:78

Variable Documentation

◆ opCtx

MemoryContext opCtx
static

Definition at line 27 of file nbtxlog.c.