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 onleft, XLogReaderState *record)
 
static void btree_xlog_dedup (XLogReaderState *record)
 
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:1458
#define BTP_INCOMPLETE_SPLIT
Definition: nbtree.h:79
#define P_INCOMPLETE_SPLIT(opaque)
Definition: nbtree.h:221
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
static char * buf
Definition: pg_test_fsync.c:67
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
uint16 btpo_flags
Definition: nbtree.h:65
#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_heap_tuples, BTMetaPageData::btm_level, BTMetaPageData::btm_magic, BTMetaPageData::btm_oldest_btpo_xact, 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_heap_tuples, xl_btree_metadata::level, MarkBufferDirty(), xl_btree_metadata::oldest_btpo_xact, 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 btm_version
Definition: nbtree.h:101
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
uint32 btm_magic
Definition: nbtree.h:100
BlockNumber root
Definition: nbtxlog.h:51
#define BTP_META
Definition: nbtree.h:75
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
BlockNumber btm_fastroot
Definition: nbtree.h:104
#define BTREE_MAGIC
Definition: nbtree.h:142
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
float8 last_cleanup_num_heap_tuples
Definition: nbtxlog.h:56
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:306
TransactionId oldest_btpo_xact
Definition: nbtxlog.h:55
#define BTPageGetMeta(p)
Definition: nbtree.h:114
bool btm_allequalimage
Definition: nbtree.h:111
#define BTREE_NOVAC_VERSION
Definition: nbtree.h:145
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define BTREE_METAPAGE
Definition: nbtree.h:141
uint32 version
Definition: nbtxlog.h:50
uint32 btm_fastlevel
Definition: nbtree.h:105
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:146
BlockNumber btm_root
Definition: nbtree.h:102
PageHeaderData * PageHeader
Definition: bufpage.h:166
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
size_t Size
Definition: c.h:466
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
float8 btm_last_cleanup_num_heap_tuples
Definition: nbtree.h:109
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2623
uint32 fastlevel
Definition: nbtxlog.h:54
uint32 btm_level
Definition: nbtree.h:103
uint32 level
Definition: nbtxlog.h:52
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:952
BlockNumber fastroot
Definition: nbtxlog.h:53
TransactionId btm_oldest_btpo_xact
Definition: nbtree.h:107
uint16 btpo_flags
Definition: nbtree.h:65
#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:53
unsigned short uint16
Definition: c.h:366
#define InvalidOffsetNumber
Definition: off.h:26
size_t Size
Definition: c.h:466
#define MAXALIGN(LEN)
Definition: c.h:691
#define MaxIndexTuplesPerPage
Definition: itup.h:145
#define elog(elevel,...)
Definition: elog.h:228
int i
#define IndexTupleSize(itup)
Definition: itup.h:71

◆ btree_mask()

void btree_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 1020 of file nbtxlog.c.

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

1021 {
1022  Page page = (Page) pagedata;
1023  BTPageOpaque maskopaq;
1024 
1026 
1027  mask_page_hint_bits(page);
1028  mask_unused_space(page);
1029 
1030  maskopaq = (BTPageOpaque) PageGetSpecialPointer(page);
1031 
1032  if (P_ISDELETED(maskopaq))
1033  {
1034  /*
1035  * Mask page content on a DELETED page since it will be re-initialized
1036  * during replay. See btree_xlog_unlink_page() for details.
1037  */
1038  mask_page_content(page);
1039  }
1040  else if (P_ISLEAF(maskopaq))
1041  {
1042  /*
1043  * In btree leaf pages, it is possible to modify the LP_FLAGS without
1044  * emitting any WAL record. Hence, mask the line pointer flags. See
1045  * _bt_killitems(), _bt_check_unique() for details.
1046  */
1047  mask_lp_flags(page);
1048  }
1049 
1050  /*
1051  * BTP_HAS_GARBAGE is just an un-logged hint bit. So, mask it. See
1052  * _bt_killitems(), _bt_check_unique() for details.
1053  */
1054  maskopaq->btpo_flags &= ~BTP_HAS_GARBAGE;
1055 
1056  /*
1057  * During replay of a btree page split, we don't set the BTP_SPLIT_END
1058  * flag of the right sibling and initialize the cycle_id to 0 for the same
1059  * page. See btree_xlog_split() for details.
1060  */
1061  maskopaq->btpo_flags &= ~BTP_SPLIT_END;
1062  maskopaq->btpo_cycleid = 0;
1063 }
#define BTP_SPLIT_END
Definition: nbtree.h:77
void mask_page_hint_bits(Page page)
Definition: bufmask.c:46
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
void mask_unused_space(Page page)
Definition: bufmask.c:71
void mask_page_content(Page page)
Definition: bufmask.c:119
BTCycleId btpo_cycleid
Definition: nbtree.h:66
#define P_ISDELETED(opaque)
Definition: nbtree.h:216
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:65
void mask_lp_flags(Page page)
Definition: bufmask.c:95
#define BTP_HAS_GARBAGE
Definition: nbtree.h:78
Pointer Page
Definition: bufpage.h:78
#define P_ISLEAF(opaque)
Definition: nbtree.h:214

◆ btree_redo()

void btree_redo ( XLogReaderState record)

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

944 {
945  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
946  MemoryContext oldCtx;
947 
948  oldCtx = MemoryContextSwitchTo(opCtx);
949  switch (info)
950  {
952  btree_xlog_insert(true, false, false, record);
953  break;
955  btree_xlog_insert(false, false, false, record);
956  break;
958  btree_xlog_insert(false, true, false, record);
959  break;
960  case XLOG_BTREE_SPLIT_L:
961  btree_xlog_split(true, record);
962  break;
963  case XLOG_BTREE_SPLIT_R:
964  btree_xlog_split(false, record);
965  break;
967  btree_xlog_insert(true, false, true, record);
968  break;
969  case XLOG_BTREE_DEDUP:
970  btree_xlog_dedup(record);
971  break;
972  case XLOG_BTREE_VACUUM:
973  btree_xlog_vacuum(record);
974  break;
975  case XLOG_BTREE_DELETE:
976  btree_xlog_delete(record);
977  break;
979  btree_xlog_mark_page_halfdead(info, record);
980  break;
983  btree_xlog_unlink_page(info, record);
984  break;
985  case XLOG_BTREE_NEWROOT:
986  btree_xlog_newroot(record);
987  break;
989  btree_xlog_reuse_page(record);
990  break;
992  _bt_restore_meta(record, 0);
993  break;
994  default:
995  elog(PANIC, "btree_redo: unknown op code %u", info);
996  }
997  MemoryContextSwitchTo(oldCtx);
999 }
static void btree_xlog_vacuum(XLogReaderState *record)
Definition: nbtxlog.c:557
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned char uint8
Definition: c.h:365
#define XLOG_BTREE_INSERT_META
Definition: nbtxlog.h:28
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:136
static void btree_xlog_delete(XLogReaderState *record)
Definition: nbtxlog.c:644
#define PANIC
Definition: elog.h:53
#define XLOG_BTREE_NEWROOT
Definition: nbtxlog.h:36
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
static void btree_xlog_newroot(XLogReaderState *record)
Definition: nbtxlog.c:881
static void btree_xlog_reuse_page(XLogReaderState *record)
Definition: nbtxlog.c:921
#define XLOG_BTREE_INSERT_LEAF
Definition: nbtxlog.h:26
#define XLOG_BTREE_VACUUM
Definition: nbtxlog.h:38
static void btree_xlog_split(bool onleft, XLogReaderState *record)
Definition: nbtxlog.c:254
#define XLOG_BTREE_UNLINK_PAGE
Definition: nbtxlog.h:34
static void btree_xlog_dedup(XLogReaderState *record)
Definition: nbtxlog.c:465
static void btree_xlog_insert(bool isleaf, bool ismeta, bool posting, XLogReaderState *record)
Definition: nbtxlog.c:163
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:284
#define XLOG_BTREE_DELETE
Definition: nbtxlog.h:33
#define XLOG_BTREE_DEDUP
Definition: nbtxlog.h:32
#define XLOG_BTREE_REUSE_PAGE
Definition: nbtxlog.h:40
#define XLOG_BTREE_MARK_PAGE_HALFDEAD
Definition: nbtxlog.h:37
#define XLOG_BTREE_SPLIT_R
Definition: nbtxlog.h:30
static MemoryContext opCtx
Definition: nbtxlog.c:27
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define XLOG_BTREE_INSERT_POST
Definition: nbtxlog.h:31
static void btree_xlog_unlink_page(uint8 info, XLogReaderState *record)
Definition: nbtxlog.c:769
#define XLOG_BTREE_INSERT_UPPER
Definition: nbtxlog.h:27
static void btree_xlog_mark_page_halfdead(uint8 info, XLogReaderState *record)
Definition: nbtxlog.c:689
#define elog(elevel,...)
Definition: elog.h:228
#define XLOG_BTREE_SPLIT_L
Definition: nbtxlog.h:29
#define XLOG_BTREE_UNLINK_PAGE_META
Definition: nbtxlog.h:35
#define XLOG_BTREE_META_CLEANUP
Definition: nbtxlog.h:42

◆ btree_xlog_cleanup()

void btree_xlog_cleanup ( void  )

Definition at line 1010 of file nbtxlog.c.

References MemoryContextDelete().

1011 {
1013  opCtx = NULL;
1014 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:211
static MemoryContext opCtx
Definition: nbtxlog.c:27

◆ btree_xlog_dedup()

static void btree_xlog_dedup ( XLogReaderState record)
static

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

466 {
467  XLogRecPtr lsn = record->EndRecPtr;
468  xl_btree_dedup *xlrec = (xl_btree_dedup *) XLogRecGetData(record);
469  Buffer buf;
470 
471  if (XLogReadBufferForRedo(record, 0, &buf) == BLK_NEEDS_REDO)
472  {
473  char *ptr = XLogRecGetBlockData(record, 0, NULL);
474  Page page = (Page) BufferGetPage(buf);
476  OffsetNumber offnum,
477  minoff,
478  maxoff;
481  Page newpage;
482 
483  state = (BTDedupState) palloc(sizeof(BTDedupStateData));
484  state->deduplicate = true; /* unused */
485  /* Conservatively use larger maxpostingsize than primary */
486  state->maxpostingsize = BTMaxItemSize(page);
487  state->base = NULL;
488  state->baseoff = InvalidOffsetNumber;
489  state->basetupsize = 0;
490  state->htids = palloc(state->maxpostingsize);
491  state->nhtids = 0;
492  state->nitems = 0;
493  state->phystupsize = 0;
494  state->nintervals = 0;
495 
496  minoff = P_FIRSTDATAKEY(opaque);
497  maxoff = PageGetMaxOffsetNumber(page);
498  newpage = PageGetTempPageCopySpecial(page);
499 
500  if (!P_RIGHTMOST(opaque))
501  {
502  ItemId itemid = PageGetItemId(page, P_HIKEY);
503  Size itemsz = ItemIdGetLength(itemid);
504  IndexTuple item = (IndexTuple) PageGetItem(page, itemid);
505 
506  if (PageAddItem(newpage, (Item) item, itemsz, P_HIKEY,
507  false, false) == InvalidOffsetNumber)
508  elog(ERROR, "deduplication failed to add highkey");
509  }
510 
511  intervals = (BTDedupInterval *) ptr;
512  for (offnum = minoff;
513  offnum <= maxoff;
514  offnum = OffsetNumberNext(offnum))
515  {
516  ItemId itemid = PageGetItemId(page, offnum);
517  IndexTuple itup = (IndexTuple) PageGetItem(page, itemid);
518 
519  if (offnum == minoff)
520  _bt_dedup_start_pending(state, itup, offnum);
521  else if (state->nintervals < xlrec->nintervals &&
522  state->baseoff == intervals[state->nintervals].baseoff &&
523  state->nitems < intervals[state->nintervals].nitems)
524  {
525  if (!_bt_dedup_save_htid(state, itup))
526  elog(ERROR, "deduplication failed to add heap tid to pending posting list");
527  }
528  else
529  {
530  _bt_dedup_finish_pending(newpage, state);
531  _bt_dedup_start_pending(state, itup, offnum);
532  }
533  }
534 
535  _bt_dedup_finish_pending(newpage, state);
536  Assert(state->nintervals == xlrec->nintervals);
537  Assert(memcmp(state->intervals, intervals,
538  state->nintervals * sizeof(BTDedupInterval)) == 0);
539 
540  if (P_HAS_GARBAGE(opaque))
541  {
542  BTPageOpaque nopaque = (BTPageOpaque) PageGetSpecialPointer(newpage);
543 
544  nopaque->btpo_flags &= ~BTP_HAS_GARBAGE;
545  }
546 
547  PageRestoreTempPage(newpage, page);
548  PageSetLSN(page, lsn);
549  MarkBufferDirty(buf);
550  }
551 
552  if (BufferIsValid(buf))
553  UnlockReleaseBuffer(buf);
554 }
char * intervals[]
IndexTuple base
Definition: nbtree.h:755
void PageRestoreTempPage(Page tempPage, Page oldPage)
Definition: bufpage.c:403
uint16 nintervals
Definition: nbtxlog.h:172
OffsetNumber baseoff
Definition: nbtree.h:756
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:244
Pointer Item
Definition: item.h:17
#define P_HAS_GARBAGE(opaque)
Definition: nbtree.h:220
#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:326
Size _bt_dedup_finish_pending(Page newpage, BTDedupState state)
Definition: nbtdedup.c:431
#define PageGetMaxOffsetNumber(page)
Definition: bufpage.h:357
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
uint16 OffsetNumber
Definition: off.h:24
Page PageGetTempPageCopySpecial(Page page)
Definition: bufpage.c:381
ItemPointer htids
Definition: nbtree.h:760
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
Size phystupsize
Definition: nbtree.h:763
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
#define ERROR
Definition: elog.h:43
BTDedupInterval intervals[MaxIndexTuplesPerPage]
Definition: nbtree.h:772
static char * buf
Definition: pg_test_fsync.c:67
bool _bt_dedup_save_htid(BTDedupState state, IndexTuple itup)
Definition: nbtdedup.c:377
IndexTupleData * IndexTuple
Definition: itup.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
uint16 nitems
Definition: nbtree.h:727
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
Definition: regguts.h:298
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
size_t Size
Definition: c.h:466
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
Size basetupsize
Definition: nbtree.h:757
Size maxpostingsize
Definition: nbtree.h:752
#define BTMaxItemSize(page)
Definition: nbtree.h:157
#define P_HIKEY
Definition: nbtree.h:242
void * palloc(Size size)
Definition: mcxt.c:949
bool deduplicate
Definition: nbtree.h:751
#define elog(elevel,...)
Definition: elog.h:228
BTDedupStateData * BTDedupState
Definition: nbtree.h:775
OffsetNumber baseoff
Definition: nbtree.h:726
uint16 btpo_flags
Definition: nbtree.h:65
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define P_RIGHTMOST(opaque)
Definition: nbtree.h:213
#define BTP_HAS_GARBAGE
Definition: nbtree.h:78
#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 644 of file nbtxlog.c.

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

Referenced by btree_redo().

645 {
646  XLogRecPtr lsn = record->EndRecPtr;
647  xl_btree_delete *xlrec = (xl_btree_delete *) XLogRecGetData(record);
648  Buffer buffer;
649  Page page;
650  BTPageOpaque opaque;
651 
652  /*
653  * If we have any conflict processing to do, it must happen before we
654  * update the page
655  */
656  if (InHotStandby)
657  {
658  RelFileNode rnode;
659 
660  XLogRecGetBlockTag(record, 0, &rnode, NULL, NULL);
661 
663  }
664 
665  /*
666  * We don't need to take a cleanup lock to apply these changes. See
667  * nbtree/README for details.
668  */
669  if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
670  {
671  char *ptr = XLogRecGetBlockData(record, 0, NULL);
672 
673  page = (Page) BufferGetPage(buffer);
674 
675  PageIndexMultiDelete(page, (OffsetNumber *) ptr, xlrec->ndeleted);
676 
677  /* Mark the page as not containing any LP_DEAD items */
678  opaque = (BTPageOpaque) PageGetSpecialPointer(page);
679  opaque->btpo_flags &= ~BTP_HAS_GARBAGE;
680 
681  PageSetLSN(page, lsn);
682  MarkBufferDirty(buffer);
683  }
684  if (BufferIsValid(buffer))
685  UnlockReleaseBuffer(buffer);
686 }
TransactionId latestRemovedXid
Definition: nbtxlog.h:189
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define InHotStandby
Definition: xlog.h:74
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
uint32 ndeleted
Definition: nbtxlog.h:190
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1481
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:828
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
Definition: standby.c:294
uint16 btpo_flags
Definition: nbtree.h:65
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define BTP_HAS_GARBAGE
Definition: nbtree.h:78
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, so that clearing the flag and inserting the downlink appear
176  * atomic to other backends. We don't bother with that during replay,
177  * because readers don't care about the incomplete-split flag and there
178  * 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:1458
Pointer Item
Definition: item.h:17
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
#define PANIC
Definition: elog.h:53
IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting, int postingoff)
Definition: nbtdedup.c:759
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
unsigned short uint16
Definition: c.h:366
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
IndexTuple CopyIndexTuple(IndexTuple source)
Definition: indextuple.c:509
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:159
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
OffsetNumber offnum
Definition: nbtxlog.h:81
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
size_t Size
Definition: c.h:466
#define OffsetNumberPrev(offsetNumber)
Definition: off.h:54
#define MAXALIGN(LEN)
Definition: c.h:691
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define elog(elevel,...)
Definition: elog.h:228
#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 689 of file nbtxlog.c.

References _bt_pageinit(), BLK_NEEDS_REDO, BTP_HALF_DEAD, BTP_LEAF, BTPageOpaqueData::btpo, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, BTreeTupleGetDownLink(), BTreeTupleSetDownLink(), BTreeTupleSetTopParent(), BufferGetPage, BufferGetPageSize, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, InvalidOffsetNumber, xl_btree_mark_page_halfdead::leftblk, BTPageOpaqueData::level, 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().

690 {
691  XLogRecPtr lsn = record->EndRecPtr;
693  Buffer buffer;
694  Page page;
695  BTPageOpaque pageop;
696  IndexTupleData trunctuple;
697 
698  /*
699  * In normal operation, we would lock all the pages this WAL record
700  * touches before changing any of them. In WAL replay, it should be okay
701  * to lock just one page at a time, since no concurrent index updates can
702  * be happening, and readers should not care whether they arrive at the
703  * target page or not (since it's surely empty).
704  */
705 
706  /* parent page */
707  if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
708  {
709  OffsetNumber poffset;
710  ItemId itemid;
711  IndexTuple itup;
712  OffsetNumber nextoffset;
713  BlockNumber rightsib;
714 
715  page = (Page) BufferGetPage(buffer);
716  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
717 
718  poffset = xlrec->poffset;
719 
720  nextoffset = OffsetNumberNext(poffset);
721  itemid = PageGetItemId(page, nextoffset);
722  itup = (IndexTuple) PageGetItem(page, itemid);
723  rightsib = BTreeTupleGetDownLink(itup);
724 
725  itemid = PageGetItemId(page, poffset);
726  itup = (IndexTuple) PageGetItem(page, itemid);
727  BTreeTupleSetDownLink(itup, rightsib);
728  nextoffset = OffsetNumberNext(poffset);
729  PageIndexTupleDelete(page, nextoffset);
730 
731  PageSetLSN(page, lsn);
732  MarkBufferDirty(buffer);
733  }
734  if (BufferIsValid(buffer))
735  UnlockReleaseBuffer(buffer);
736 
737  /* Rewrite the leaf page as a halfdead page */
738  buffer = XLogInitBufferForRedo(record, 0);
739  page = (Page) BufferGetPage(buffer);
740 
741  _bt_pageinit(page, BufferGetPageSize(buffer));
742  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
743 
744  pageop->btpo_prev = xlrec->leftblk;
745  pageop->btpo_next = xlrec->rightblk;
746  pageop->btpo.level = 0;
747  pageop->btpo_flags = BTP_HALF_DEAD | BTP_LEAF;
748  pageop->btpo_cycleid = 0;
749 
750  /*
751  * Construct a dummy hikey item that points to the next parent to be
752  * deleted (if any).
753  */
754  MemSet(&trunctuple, 0, sizeof(IndexTupleData));
755  trunctuple.t_info = sizeof(IndexTupleData);
756  BTreeTupleSetTopParent(&trunctuple, xlrec->topparent);
757 
758  if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY,
759  false, false) == InvalidOffsetNumber)
760  elog(ERROR, "could not add dummy high key to half-dead page");
761 
762  PageSetLSN(page, lsn);
763  MarkBufferDirty(buffer);
764  UnlockReleaseBuffer(buffer);
765 }
BlockNumber btpo_next
Definition: nbtree.h:59
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
Definition: bufpage.c:719
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define BTP_LEAF
Definition: nbtree.h:72
#define BTP_HALF_DEAD
Definition: nbtree.h:76
union BTPageOpaqueData::@46 btpo
Pointer Item
Definition: item.h:17
static BlockNumber BTreeTupleGetDownLink(IndexTuple pivot)
Definition: nbtree.h:431
#define MemSet(start, val, len)
Definition: c.h:971
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
uint16 OffsetNumber
Definition: off.h:24
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
#define ERROR
Definition: elog.h:43
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:306
BTCycleId btpo_cycleid
Definition: nbtree.h:66
BlockNumber btpo_prev
Definition: nbtree.h:58
IndexTupleData * IndexTuple
Definition: itup.h:53
static void BTreeTupleSetDownLink(IndexTuple pivot, BlockNumber blkno)
Definition: nbtree.h:437
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
uint32 level
Definition: nbtree.h:62
struct IndexTupleData IndexTupleData
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:146
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
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:113
#define P_HIKEY
Definition: nbtree.h:242
#define elog(elevel,...)
Definition: elog.h:228
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:952
unsigned short t_info
Definition: itup.h:49
uint16 btpo_flags
Definition: nbtree.h:65
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
static void BTreeTupleSetTopParent(IndexTuple leafhikey, BlockNumber blkno)
Definition: nbtree.h:505
#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 881 of file nbtxlog.c.

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

Referenced by btree_redo().

882 {
883  XLogRecPtr lsn = record->EndRecPtr;
884  xl_btree_newroot *xlrec = (xl_btree_newroot *) XLogRecGetData(record);
885  Buffer buffer;
886  Page page;
887  BTPageOpaque pageop;
888  char *ptr;
889  Size len;
890 
891  buffer = XLogInitBufferForRedo(record, 0);
892  page = (Page) BufferGetPage(buffer);
893 
894  _bt_pageinit(page, BufferGetPageSize(buffer));
895  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
896 
897  pageop->btpo_flags = BTP_ROOT;
898  pageop->btpo_prev = pageop->btpo_next = P_NONE;
899  pageop->btpo.level = xlrec->level;
900  if (xlrec->level == 0)
901  pageop->btpo_flags |= BTP_LEAF;
902  pageop->btpo_cycleid = 0;
903 
904  if (xlrec->level > 0)
905  {
906  ptr = XLogRecGetBlockData(record, 0, &len);
907  _bt_restore_page(page, ptr, len);
908 
909  /* Clear the incomplete-split flag in left child */
910  _bt_clear_incomplete_split(record, 1);
911  }
912 
913  PageSetLSN(page, lsn);
914  MarkBufferDirty(buffer);
915  UnlockReleaseBuffer(buffer);
916 
917  _bt_restore_meta(record, 2);
918 }
#define BTP_ROOT
Definition: nbtree.h:73
BlockNumber btpo_next
Definition: nbtree.h:59
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define BTP_LEAF
Definition: nbtree.h:72
union BTPageOpaqueData::@46 btpo
#define P_NONE
Definition: nbtree.h:206
uint32 level
Definition: nbtxlog.h:319
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:306
BTCycleId btpo_cycleid
Definition: nbtree.h:66
BlockNumber btpo_prev
Definition: nbtree.h:58
static void _bt_clear_incomplete_split(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:142
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
uint32 level
Definition: nbtree.h:62
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
static void _bt_restore_page(Page page, char *from, int len)
Definition: nbtxlog.c:38
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:146
uint64 XLogRecPtr
Definition: xlogdefs.h:21
size_t Size
Definition: c.h:466
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:952
uint16 btpo_flags
Definition: nbtree.h:65
#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 921 of file nbtxlog.c.

References InHotStandby, xl_btree_reuse_page::latestRemovedXid, xl_btree_reuse_page::node, ResolveRecoveryConflictWithSnapshot(), and XLogRecGetData.

Referenced by btree_redo().

922 {
924 
925  /*
926  * Btree reuse_page records exist to provide a conflict point when we
927  * reuse pages in the index via the FSM. That's all they do though.
928  *
929  * latestRemovedXid was the page's btpo.xact. The btpo.xact <
930  * RecentGlobalXmin test in _bt_page_recyclable() conceptually mirrors the
931  * pgxact->xmin > limitXmin test in GetConflictingVirtualXIDs().
932  * Consequently, one XID value achieves the same exclusion effect on
933  * master and standby.
934  */
935  if (InHotStandby)
936  {
938  xlrec->node);
939  }
940 }
RelFileNode node
Definition: nbtxlog.h:206
#define InHotStandby
Definition: xlog.h:74
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void ResolveRecoveryConflictWithSnapshot(TransactionId latestRemovedXid, RelFileNode node)
Definition: standby.c:294
TransactionId latestRemovedXid
Definition: nbtxlog.h:208

◆ btree_xlog_split()

static void btree_xlog_split ( bool  onleft,
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, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, BufferGetPage, BufferGetPageSize, BufferIsValid, CopyIndexTuple(), elog, XLogReaderState::EndRecPtr, ERROR, xl_btree_split::firstright, IndexTupleSize, InvalidOffsetNumber, ItemIdGetLength, BTPageOpaqueData::level, 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, PANIC, 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 lbuf;
260  Buffer rbuf;
261  Page rpage;
262  BTPageOpaque ropaque;
263  char *datapos;
264  Size datalen;
265  BlockNumber leftsib;
266  BlockNumber rightsib;
267  BlockNumber rnext;
268 
269  XLogRecGetBlockTag(record, 0, NULL, NULL, &leftsib);
270  XLogRecGetBlockTag(record, 1, NULL, NULL, &rightsib);
271  if (!XLogRecGetBlockTag(record, 2, NULL, NULL, &rnext))
272  rnext = P_NONE;
273 
274  /*
275  * Clear the incomplete split flag on the left sibling of the child page
276  * this is a downlink for. (Like in btree_xlog_insert, this can be done
277  * before locking the other pages)
278  */
279  if (!isleaf)
280  _bt_clear_incomplete_split(record, 3);
281 
282  /* Reconstruct right (new) sibling page from scratch */
283  rbuf = XLogInitBufferForRedo(record, 1);
284  datapos = XLogRecGetBlockData(record, 1, &datalen);
285  rpage = (Page) BufferGetPage(rbuf);
286 
287  _bt_pageinit(rpage, BufferGetPageSize(rbuf));
288  ropaque = (BTPageOpaque) PageGetSpecialPointer(rpage);
289 
290  ropaque->btpo_prev = leftsib;
291  ropaque->btpo_next = rnext;
292  ropaque->btpo.level = xlrec->level;
293  ropaque->btpo_flags = isleaf ? BTP_LEAF : 0;
294  ropaque->btpo_cycleid = 0;
295 
296  _bt_restore_page(rpage, datapos, datalen);
297 
298  PageSetLSN(rpage, lsn);
299  MarkBufferDirty(rbuf);
300 
301  /* Now reconstruct left (original) sibling page */
302  if (XLogReadBufferForRedo(record, 0, &lbuf) == BLK_NEEDS_REDO)
303  {
304  /*
305  * To retain the same physical order of the tuples that they had, we
306  * initialize a temporary empty page for the left page and add all the
307  * items to that in item number order. This mirrors how _bt_split()
308  * works. Retaining the same physical order makes WAL consistency
309  * checking possible. See also _bt_restore_page(), which does the
310  * same for the right page.
311  */
312  Page lpage = (Page) BufferGetPage(lbuf);
314  OffsetNumber off;
315  IndexTuple newitem = NULL,
316  left_hikey = NULL,
317  nposting = NULL;
318  Size newitemsz = 0,
319  left_hikeysz = 0;
320  Page newlpage;
321  OffsetNumber leftoff,
322  replacepostingoff = InvalidOffsetNumber;
323 
324  datapos = XLogRecGetBlockData(record, 0, &datalen);
325 
326  if (onleft || xlrec->postingoff != 0)
327  {
328  newitem = (IndexTuple) datapos;
329  newitemsz = MAXALIGN(IndexTupleSize(newitem));
330  datapos += newitemsz;
331  datalen -= newitemsz;
332 
333  if (xlrec->postingoff != 0)
334  {
335  ItemId itemid;
336  IndexTuple oposting;
337 
338  /* Posting list must be at offset number before new item's */
339  replacepostingoff = OffsetNumberPrev(xlrec->newitemoff);
340 
341  /* Use mutable, aligned newitem copy in _bt_swap_posting() */
342  newitem = CopyIndexTuple(newitem);
343  itemid = PageGetItemId(lpage, replacepostingoff);
344  oposting = (IndexTuple) PageGetItem(lpage, itemid);
345  nposting = _bt_swap_posting(newitem, oposting,
346  xlrec->postingoff);
347  }
348  }
349 
350  /*
351  * Extract left hikey and its size. We assume that 16-bit alignment
352  * is enough to apply IndexTupleSize (since it's fetching from a
353  * uint16 field).
354  */
355  left_hikey = (IndexTuple) datapos;
356  left_hikeysz = MAXALIGN(IndexTupleSize(left_hikey));
357  datapos += left_hikeysz;
358  datalen -= left_hikeysz;
359 
360  Assert(datalen == 0);
361 
362  newlpage = PageGetTempPageCopySpecial(lpage);
363 
364  /* Set high key */
365  leftoff = P_HIKEY;
366  if (PageAddItem(newlpage, (Item) left_hikey, left_hikeysz,
367  P_HIKEY, false, false) == InvalidOffsetNumber)
368  elog(PANIC, "failed to add high key to left page after split");
369  leftoff = OffsetNumberNext(leftoff);
370 
371  for (off = P_FIRSTDATAKEY(lopaque); off < xlrec->firstright; off++)
372  {
373  ItemId itemid;
374  Size itemsz;
375  IndexTuple item;
376 
377  /* Add replacement posting list when required */
378  if (off == replacepostingoff)
379  {
380  Assert(onleft || xlrec->firstright == xlrec->newitemoff);
381  if (PageAddItem(newlpage, (Item) nposting,
382  MAXALIGN(IndexTupleSize(nposting)), leftoff,
383  false, false) == InvalidOffsetNumber)
384  elog(ERROR, "failed to add new posting list item to left page after split");
385  leftoff = OffsetNumberNext(leftoff);
386  continue; /* don't insert oposting */
387  }
388 
389  /* add the new item if it was inserted on left page */
390  else if (onleft && off == xlrec->newitemoff)
391  {
392  if (PageAddItem(newlpage, (Item) newitem, newitemsz, leftoff,
393  false, false) == InvalidOffsetNumber)
394  elog(ERROR, "failed to add new item to left page after split");
395  leftoff = OffsetNumberNext(leftoff);
396  }
397 
398  itemid = PageGetItemId(lpage, off);
399  itemsz = ItemIdGetLength(itemid);
400  item = (IndexTuple) PageGetItem(lpage, itemid);
401  if (PageAddItem(newlpage, (Item) item, itemsz, leftoff,
402  false, false) == InvalidOffsetNumber)
403  elog(ERROR, "failed to add old item to left page after split");
404  leftoff = OffsetNumberNext(leftoff);
405  }
406 
407  /* cope with possibility that newitem goes at the end */
408  if (onleft && off == xlrec->newitemoff)
409  {
410  if (PageAddItem(newlpage, (Item) newitem, newitemsz, leftoff,
411  false, false) == InvalidOffsetNumber)
412  elog(ERROR, "failed to add new item to left page after split");
413  leftoff = OffsetNumberNext(leftoff);
414  }
415 
416  PageRestoreTempPage(newlpage, lpage);
417 
418  /* Fix opaque fields */
419  lopaque->btpo_flags = BTP_INCOMPLETE_SPLIT;
420  if (isleaf)
421  lopaque->btpo_flags |= BTP_LEAF;
422  lopaque->btpo_next = rightsib;
423  lopaque->btpo_cycleid = 0;
424 
425  PageSetLSN(lpage, lsn);
426  MarkBufferDirty(lbuf);
427  }
428 
429  /*
430  * We no longer need the buffers. They must be released together, so that
431  * readers cannot observe two inconsistent halves.
432  */
433  if (BufferIsValid(lbuf))
434  UnlockReleaseBuffer(lbuf);
435  UnlockReleaseBuffer(rbuf);
436 
437  /*
438  * Fix left-link of the page to the right of the new right sibling.
439  *
440  * Note: in normal operation, we do this while still holding lock on the
441  * two split pages. However, that's not necessary for correctness in WAL
442  * replay, because no other index update can be in progress, and readers
443  * will cope properly when following an obsolete left-link.
444  */
445  if (rnext != P_NONE)
446  {
447  Buffer buffer;
448 
449  if (XLogReadBufferForRedo(record, 2, &buffer) == BLK_NEEDS_REDO)
450  {
451  Page page = (Page) BufferGetPage(buffer);
453 
454  pageop->btpo_prev = rightsib;
455 
456  PageSetLSN(page, lsn);
457  MarkBufferDirty(buffer);
458  }
459  if (BufferIsValid(buffer))
460  UnlockReleaseBuffer(buffer);
461  }
462 }
BlockNumber btpo_next
Definition: nbtree.h:59
void PageRestoreTempPage(Page tempPage, Page oldPage)
Definition: bufpage.c:403
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define P_FIRSTDATAKEY(opaque)
Definition: nbtree.h:244
#define BTP_LEAF
Definition: nbtree.h:72
union BTPageOpaqueData::@46 btpo
Pointer Item
Definition: item.h:17
#define P_NONE
Definition: nbtree.h:206
#define BTP_INCOMPLETE_SPLIT
Definition: nbtree.h:79
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
#define PANIC
Definition: elog.h:53
IndexTuple _bt_swap_posting(IndexTuple newitem, IndexTuple oposting, int postingoff)
Definition: nbtdedup.c:759
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
uint16 OffsetNumber
Definition: off.h:24
Page PageGetTempPageCopySpecial(Page page)
Definition: bufpage.c:381
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
#define ERROR
Definition: elog.h:43
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:306
OffsetNumber newitemoff
Definition: nbtxlog.h:157
BTCycleId btpo_cycleid
Definition: nbtree.h:66
BlockNumber btpo_prev
Definition: nbtree.h:58
IndexTuple CopyIndexTuple(IndexTuple source)
Definition: indextuple.c:509
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:159
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
uint32 level
Definition: nbtree.h:62
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1481
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
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:146
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:738
OffsetNumber firstright
Definition: nbtxlog.h:156
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
size_t Size
Definition: c.h:466
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define OffsetNumberPrev(offsetNumber)
Definition: off.h:54
#define MAXALIGN(LEN)
Definition: c.h:691
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define P_HIKEY
Definition: nbtree.h:242
#define elog(elevel,...)
Definition: elog.h:228
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:952
uint16 postingoff
Definition: nbtxlog.h:158
uint16 btpo_flags
Definition: nbtree.h:65
#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 1002 of file nbtxlog.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, and CurrentMemoryContext.

1003 {
1005  "Btree recovery temporary context",
1007 }
#define AllocSetContextCreate
Definition: memutils.h:170
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
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 769 of file nbtxlog.c.

References _bt_pageinit(), _bt_restore_meta(), BLK_NEEDS_REDO, BTP_DELETED, BTP_HALF_DEAD, BTP_LEAF, BTPageOpaqueData::btpo, BTPageOpaqueData::btpo_cycleid, BTPageOpaqueData::btpo_flags, BTPageOpaqueData::btpo_next, BTPageOpaqueData::btpo_prev, xl_btree_unlink_page::btpo_xact, BTreeTupleSetTopParent(), BufferGetPage, BufferGetPageSize, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, InvalidOffsetNumber, xl_btree_unlink_page::leafleftsib, xl_btree_unlink_page::leafrightsib, xl_btree_unlink_page::leftsib, BTPageOpaqueData::level, MarkBufferDirty(), MemSet, P_HIKEY, P_NONE, PageAddItem, PageGetSpecialPointer, PageSetLSN, xl_btree_unlink_page::rightsib, IndexTupleData::t_info, xl_btree_unlink_page::topparent, UnlockReleaseBuffer(), BTPageOpaqueData::xact, XLOG_BTREE_UNLINK_PAGE_META, XLogInitBufferForRedo(), XLogReadBufferForRedo(), XLogRecGetData, and XLogRecHasBlockRef.

Referenced by btree_redo().

770 {
771  XLogRecPtr lsn = record->EndRecPtr;
773  BlockNumber leftsib;
774  BlockNumber rightsib;
775  Buffer buffer;
776  Page page;
777  BTPageOpaque pageop;
778 
779  leftsib = xlrec->leftsib;
780  rightsib = xlrec->rightsib;
781 
782  /*
783  * In normal operation, we would lock all the pages this WAL record
784  * touches before changing any of them. In WAL replay, it should be okay
785  * to lock just one page at a time, since no concurrent index updates can
786  * be happening, and readers should not care whether they arrive at the
787  * target page or not (since it's surely empty).
788  */
789 
790  /* Fix left-link of right sibling */
791  if (XLogReadBufferForRedo(record, 2, &buffer) == BLK_NEEDS_REDO)
792  {
793  page = (Page) BufferGetPage(buffer);
794  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
795  pageop->btpo_prev = leftsib;
796 
797  PageSetLSN(page, lsn);
798  MarkBufferDirty(buffer);
799  }
800  if (BufferIsValid(buffer))
801  UnlockReleaseBuffer(buffer);
802 
803  /* Fix right-link of left sibling, if any */
804  if (leftsib != P_NONE)
805  {
806  if (XLogReadBufferForRedo(record, 1, &buffer) == BLK_NEEDS_REDO)
807  {
808  page = (Page) BufferGetPage(buffer);
809  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
810  pageop->btpo_next = rightsib;
811 
812  PageSetLSN(page, lsn);
813  MarkBufferDirty(buffer);
814  }
815  if (BufferIsValid(buffer))
816  UnlockReleaseBuffer(buffer);
817  }
818 
819  /* Rewrite target page as empty deleted page */
820  buffer = XLogInitBufferForRedo(record, 0);
821  page = (Page) BufferGetPage(buffer);
822 
823  _bt_pageinit(page, BufferGetPageSize(buffer));
824  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
825 
826  pageop->btpo_prev = leftsib;
827  pageop->btpo_next = rightsib;
828  pageop->btpo.xact = xlrec->btpo_xact;
829  pageop->btpo_flags = BTP_DELETED;
830  pageop->btpo_cycleid = 0;
831 
832  PageSetLSN(page, lsn);
833  MarkBufferDirty(buffer);
834  UnlockReleaseBuffer(buffer);
835 
836  /*
837  * If we deleted a parent of the targeted leaf page, instead of the leaf
838  * itself, update the leaf to point to the next remaining child in the
839  * branch.
840  */
841  if (XLogRecHasBlockRef(record, 3))
842  {
843  /*
844  * There is no real data on the page, so we just re-create it from
845  * scratch using the information from the WAL record.
846  */
847  IndexTupleData trunctuple;
848 
849  buffer = XLogInitBufferForRedo(record, 3);
850  page = (Page) BufferGetPage(buffer);
851 
852  _bt_pageinit(page, BufferGetPageSize(buffer));
853  pageop = (BTPageOpaque) PageGetSpecialPointer(page);
854 
855  pageop->btpo_flags = BTP_HALF_DEAD | BTP_LEAF;
856  pageop->btpo_prev = xlrec->leafleftsib;
857  pageop->btpo_next = xlrec->leafrightsib;
858  pageop->btpo.level = 0;
859  pageop->btpo_cycleid = 0;
860 
861  /* Add a dummy hikey item */
862  MemSet(&trunctuple, 0, sizeof(IndexTupleData));
863  trunctuple.t_info = sizeof(IndexTupleData);
864  BTreeTupleSetTopParent(&trunctuple, xlrec->topparent);
865 
866  if (PageAddItem(page, (Item) &trunctuple, sizeof(IndexTupleData), P_HIKEY,
867  false, false) == InvalidOffsetNumber)
868  elog(ERROR, "could not add dummy high key to half-dead page");
869 
870  PageSetLSN(page, lsn);
871  MarkBufferDirty(buffer);
872  UnlockReleaseBuffer(buffer);
873  }
874 
875  /* Update metapage if needed */
876  if (info == XLOG_BTREE_UNLINK_PAGE_META)
877  _bt_restore_meta(record, 4);
878 }
BlockNumber btpo_next
Definition: nbtree.h:59
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
#define BTP_LEAF
Definition: nbtree.h:72
#define BTP_HALF_DEAD
Definition: nbtree.h:76
union BTPageOpaqueData::@46 btpo
Pointer Item
Definition: item.h:17
#define P_NONE
Definition: nbtree.h:206
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:291
#define MemSet(start, val, len)
Definition: c.h:971
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:416
uint32 BlockNumber
Definition: block.h:31
#define BTP_DELETED
Definition: nbtree.h:74
TransactionId xact
Definition: nbtree.h:63
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
static void _bt_restore_meta(XLogReaderState *record, uint8 block_id)
Definition: nbtxlog.c:85
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
#define ERROR
Definition: elog.h:43
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:306
BTCycleId btpo_cycleid
Definition: nbtree.h:66
BlockNumber btpo_prev
Definition: nbtree.h:58
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
uint32 level
Definition: nbtree.h:62
struct IndexTupleData IndexTupleData
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:146
#define InvalidOffsetNumber
Definition: off.h:26
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:294
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
#define P_HIKEY
Definition: nbtree.h:242
#define elog(elevel,...)
Definition: elog.h:228
void _bt_pageinit(Page page, Size size)
Definition: nbtpage.c:952
#define XLOG_BTREE_UNLINK_PAGE_META
Definition: nbtxlog.h:35
unsigned short t_info
Definition: itup.h:49
uint16 btpo_flags
Definition: nbtree.h:65
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
static void BTreeTupleSetTopParent(IndexTuple leafhikey, BlockNumber blkno)
Definition: nbtree.h:505
Pointer Page
Definition: bufpage.h:78

◆ btree_xlog_vacuum()

static void btree_xlog_vacuum ( XLogReaderState record)
static

Definition at line 557 of file nbtxlog.c.

References _bt_update_posting(), BLK_NEEDS_REDO, BTP_HAS_GARBAGE, BTPageOpaqueData::btpo_flags, BufferGetPage, BufferIsValid, BTVacuumPostingData::deletetids, elog, XLogReaderState::EndRecPtr, i, IndexTupleSize, BTVacuumPostingData::itup, MarkBufferDirty(), MAXALIGN, xl_btree_vacuum::ndeleted, xl_btree_update::ndeletedtids, BTVacuumPostingData::ndeletedtids, xl_btree_vacuum::nupdated, offsetof, PageGetItem, PageGetItemId, PageGetSpecialPointer, PageIndexMultiDelete(), PageIndexTupleOverwrite(), PageSetLSN, palloc(), PANIC, pfree(), RBM_NORMAL, SizeOfBtreeUpdate, UnlockReleaseBuffer(), BTVacuumPostingData::updatedoffset, XLogReadBufferForRedoExtended(), XLogRecGetBlockData(), and XLogRecGetData.

Referenced by btree_redo().

558 {
559  XLogRecPtr lsn = record->EndRecPtr;
560  xl_btree_vacuum *xlrec = (xl_btree_vacuum *) XLogRecGetData(record);
561  Buffer buffer;
562  Page page;
563  BTPageOpaque opaque;
564 
565  /*
566  * We need to take a cleanup lock here, just like btvacuumpage(). However,
567  * it isn't necessary to exhaustively get a cleanup lock on every block in
568  * the index during recovery (just getting a cleanup lock on pages with
569  * items to kill suffices). See nbtree/README for details.
570  */
571  if (XLogReadBufferForRedoExtended(record, 0, RBM_NORMAL, true, &buffer)
572  == BLK_NEEDS_REDO)
573  {
574  char *ptr = XLogRecGetBlockData(record, 0, NULL);
575 
576  page = (Page) BufferGetPage(buffer);
577 
578  if (xlrec->nupdated > 0)
579  {
580  OffsetNumber *updatedoffsets;
581  xl_btree_update *updates;
582 
583  updatedoffsets = (OffsetNumber *)
584  (ptr + xlrec->ndeleted * sizeof(OffsetNumber));
585  updates = (xl_btree_update *) ((char *) updatedoffsets +
586  xlrec->nupdated *
587  sizeof(OffsetNumber));
588 
589  for (int i = 0; i < xlrec->nupdated; i++)
590  {
591  BTVacuumPosting vacposting;
592  IndexTuple origtuple;
593  ItemId itemid;
594  Size itemsz;
595 
596  itemid = PageGetItemId(page, updatedoffsets[i]);
597  origtuple = (IndexTuple) PageGetItem(page, itemid);
598 
599  vacposting = palloc(offsetof(BTVacuumPostingData, deletetids) +
600  updates->ndeletedtids * sizeof(uint16));
601  vacposting->updatedoffset = updatedoffsets[i];
602  vacposting->itup = origtuple;
603  vacposting->ndeletedtids = updates->ndeletedtids;
604  memcpy(vacposting->deletetids,
605  (char *) updates + SizeOfBtreeUpdate,
606  updates->ndeletedtids * sizeof(uint16));
607 
608  _bt_update_posting(vacposting);
609 
610  /* Overwrite updated version of tuple */
611  itemsz = MAXALIGN(IndexTupleSize(vacposting->itup));
612  if (!PageIndexTupleOverwrite(page, updatedoffsets[i],
613  (Item) vacposting->itup, itemsz))
614  elog(PANIC, "failed to update partially dead item");
615 
616  pfree(vacposting->itup);
617  pfree(vacposting);
618 
619  /* advance to next xl_btree_update from array */
620  updates = (xl_btree_update *)
621  ((char *) updates + SizeOfBtreeUpdate +
622  updates->ndeletedtids * sizeof(uint16));
623  }
624  }
625 
626  if (xlrec->ndeleted > 0)
627  PageIndexMultiDelete(page, (OffsetNumber *) ptr, xlrec->ndeleted);
628 
629  /*
630  * Mark the page as not containing any LP_DEAD items --- see comments
631  * in _bt_delitems_vacuum().
632  */
633  opaque = (BTPageOpaque) PageGetSpecialPointer(page);
634  opaque->btpo_flags &= ~BTP_HAS_GARBAGE;
635 
636  PageSetLSN(page, lsn);
637  MarkBufferDirty(buffer);
638  }
639  if (BufferIsValid(buffer))
640  UnlockReleaseBuffer(buffer);
641 }
uint16 ndeletedtids
Definition: nbtree.h:791
void _bt_update_posting(BTVacuumPosting vacposting)
Definition: nbtdedup.c:661
#define SizeOfBtreeUpdate
Definition: nbtxlog.h:225
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1458
OffsetNumber updatedoffset
Definition: nbtree.h:788
IndexTuple itup
Definition: nbtree.h:787
Pointer Item
Definition: item.h:17
uint16 nupdated
Definition: nbtxlog.h:243
#define PANIC
Definition: elog.h:53
BTPageOpaqueData * BTPageOpaque
Definition: nbtree.h:69
XLogRecPtr EndRecPtr
Definition: xlogreader.h:135
uint16 OffsetNumber
Definition: off.h:24
unsigned short uint16
Definition: c.h:366
void pfree(void *pointer)
Definition: mcxt.c:1056
#define XLogRecGetData(decoder)
Definition: xlogreader.h:288
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3398
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, Item newtup, Size newsize)
Definition: bufpage.c:1060
IndexTupleData * IndexTuple
Definition: itup.h:53
#define BufferGetPage(buffer)
Definition: bufmgr.h:159
uint16 ndeleted
Definition: nbtxlog.h:242
#define PageGetItemId(page, offsetNumber)
Definition: bufpage.h:235
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:1505
uint16 deletetids[FLEXIBLE_ARRAY_MEMBER]
Definition: nbtree.h:792
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
Definition: bufpage.c:828
size_t Size
Definition: c.h:466
#define PageGetSpecialPointer(page)
Definition: bufpage.h:326
#define MAXALIGN(LEN)
Definition: c.h:691
#define BufferIsValid(bufnum)
Definition: bufmgr.h:113
void * palloc(Size size)
Definition: mcxt.c:949
XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)
Definition: xlogutils.c:331
#define elog(elevel,...)
Definition: elog.h:228
int i
uint16 btpo_flags
Definition: nbtree.h:65
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23
#define offsetof(type, field)
Definition: c.h:661
#define BTP_HAS_GARBAGE
Definition: nbtree.h:78
uint16 ndeletedtids
Definition: nbtxlog.h:220
#define PageGetItem(page, itemId)
Definition: bufpage.h:340
Pointer Page
Definition: bufpage.h:78
#define IndexTupleSize(itup)
Definition: itup.h:71

Variable Documentation

◆ opCtx

MemoryContext opCtx
static

Definition at line 27 of file nbtxlog.c.