49 Size *updatedbuflen,
bool needswal);
157 (
errcode(ERRCODE_INDEX_CORRUPTED),
158 errmsg(
"index \"%s\" is not a btree",
164 (
errcode(ERRCODE_INDEX_CORRUPTED),
165 errmsg(
"version mismatch in index \"%s\": file version %d, "
166 "current version %d, minimal supported version %d",
219 if (prev_num_delpages > 0 &&
548 elog(
ERROR,
"no live root page found in index \"%s\"",
554 elog(
ERROR,
"root page %u of index \"%s\" has level %u, expected %u",
611 (
errcode(ERRCODE_INDEX_CORRUPTED),
612 errmsg(
"index \"%s\" is not a btree",
618 (
errcode(ERRCODE_INDEX_CORRUPTED),
619 errmsg(
"version mismatch in index \"%s\": file version %d, "
620 "current version %d, minimal supported version %d",
651 elog(
ERROR,
"no live root page found in index \"%s\"",
657 elog(
ERROR,
"root page %u of index \"%s\" has level %u, expected %u",
810 (
errcode(ERRCODE_INDEX_CORRUPTED),
811 errmsg(
"index \"%s\" contains unexpected zero page at block %u",
814 errhint(
"Please REINDEX it.")));
821 (
errcode(ERRCODE_INDEX_CORRUPTED),
822 errmsg(
"index \"%s\" contains corrupted page at block %u",
825 errhint(
"Please REINDEX it.")));
946 xlrec_reuse.
block = blkno;
961 elog(
DEBUG2,
"FSM returned nonrecyclable page");
966 elog(
DEBUG2,
"FSM returned nonlockable page");
1162 char *updatedbuf = NULL;
1163 Size updatedbuflen = 0;
1167 Assert(ndeletable > 0 || nupdatable > 0);
1172 updatedoffsets, &updatedbuflen,
1190 for (
int i = 0;
i < nupdatable;
i++)
1196 itup = updatable[
i]->
itup;
1199 elog(
PANIC,
"failed to update partially dead item in block %u of index \"%s\"",
1232 xlrec_vacuum.
ndeleted = ndeletable;
1233 xlrec_vacuum.
nupdated = nupdatable;
1258 if (updatedbuf != NULL)
1261 for (
int i = 0;
i < nupdatable;
i++)
1262 pfree(updatable[
i]->itup);
1292 char *updatedbuf = NULL;
1293 Size updatedbuflen = 0;
1297 Assert(ndeletable > 0 || nupdatable > 0);
1302 updatedoffsets, &updatedbuflen,
1309 for (
int i = 0;
i < nupdatable;
i++)
1315 itup = updatable[
i]->
itup;
1318 elog(
PANIC,
"failed to update partially dead item in block %u of index \"%s\"",
1349 xlrec_delete.
ndeleted = ndeletable;
1350 xlrec_delete.
nupdated = nupdatable;
1376 if (updatedbuf != NULL)
1379 for (
int i = 0;
i < nupdatable;
i++)
1380 pfree(updatable[
i]->itup);
1408 char *updatedbuf = NULL;
1414 for (
int i = 0;
i < nupdatable;
i++)
1436 updatedbuf =
palloc(buflen);
1437 *updatedbuflen = buflen;
1438 for (
int i = 0;
i < nupdatable;
i++)
1450 memcpy(updatedbuf + offset, vacposting->
deletetids, itemsz);
1468 Assert(indexdelete1->
id != indexdelete2->
id);
1564 if (idxoffnum == postingidxoffnum)
1583 deletable[ndeletable++] = idxoffnum;
1595 postingidxoffnum = idxoffnum;
1599 for (
int p = 0; p < nitem; p++)
1610 for (; nestedi < delstate->
ndeltids; nestedi++)
1638 if (vacposting == NULL)
1642 vacposting->
itup = itup;
1651 if (vacposting == NULL)
1658 deletable[ndeletable++] = idxoffnum;
1667 updatable[nupdatable++] = vacposting;
1673 deletable, ndeletable, updatable, nupdatable);
1676 for (
int i = 0;
i < nupdatable;
i++)
1804 bool rightsib_empty;
1859 (
errcode(ERRCODE_INDEX_CORRUPTED),
1860 errmsg(
"index \"%s\" contains a half-dead internal page",
1862 errhint(
"This can be caused by an interrupted VACUUM in version 9.3 or older, before upgrade. Please REINDEX it.")));
1866 (
errcode(ERRCODE_INDEX_CORRUPTED),
1867 errmsg_internal(
"found deleted block %u while following right link from block %u in index \"%s\"",
1948 Assert(leafblkno == scanblkno);
2017 rightsib_empty =
false;
2023 &rightsib_empty, vstate))
2065 if (!rightsib_empty)
2130 elog(
DEBUG1,
"could not delete page %u because its right sibling %u is half-dead",
2131 leafblkno, leafrightsib);
2150 topparent = leafblkno;
2151 topparentrightsib = leafrightsib;
2153 &subtreeparent, &poffset,
2154 &topparent, &topparentrightsib))
2160#ifdef USE_ASSERT_CHECKING
2185 (
errcode(ERRCODE_INDEX_CORRUPTED),
2186 errmsg_internal(
"right sibling %u of block %u is not next child %u of block %u in index \"%s\"",
2187 topparentrightsib, topparent,
2240 if (topparent != leafblkno)
2246 elog(
ERROR,
"could not overwrite high key in half-dead page");
2260 if (topparent != leafblkno)
2336 bool rightsib_is_rightmost;
2372 leftsib = leafleftsib;
2378 Assert(target != leafblkno);
2404 if (target != leafblkno)
2413 bool leftsibvalid =
true;
2426 leftsibvalid =
false;
2439 (
errcode(ERRCODE_INDEX_CORRUPTED),
2440 errmsg_internal(
"valid left sibling for deletion target could not be located: "
2441 "left sibling %u of target %u with leafblkno %u and scanblkno %u on level %u of index \"%s\"",
2442 leftsib, target, leafblkno, scanblkno,
2447 if (target != leafblkno)
2475 elog(
ERROR,
"target page changed status unexpectedly in block %u of index \"%s\"",
2480 (
errcode(ERRCODE_INDEX_CORRUPTED),
2481 errmsg_internal(
"target page left link unexpectedly changed from %u to %u in block %u of index \"%s\"",
2485 if (target == leafblkno)
2489 elog(
ERROR,
"target leaf page changed status unexpectedly in block %u of index \"%s\"",
2501 elog(
ERROR,
"target internal page on level %u changed status unexpectedly in block %u of index \"%s\"",
2509 if (leaftopparent == leafblkno)
2537 (
errcode(ERRCODE_INDEX_CORRUPTED),
2539 "right sibling %u of target %u with leafblkno %u "
2540 "and scanblkno %u spuriously links to non-target %u "
2541 "on level %u of index \"%s\"",
2542 rightsib, target, leafblkno,
2551 if (target != leafblkno)
2569 if (leftsib ==
P_NONE && rightsib_is_rightmost)
2629 if (target != leafblkno)
2670 if (target != leafblkno)
2687 if (target != leafblkno)
2693 xlrec.
level = targetlevel;
2737 if (target != leafblkno)
2756 if (target != leafblkno)
2769 if (target <= scanblkno)
2850 (
errcode(ERRCODE_INDEX_CORRUPTED),
2851 errmsg_internal(
"failed to re-find parent key in index \"%s\" for deletion target page %u",
2879 if (parentoffset < maxoff)
2885 *subtreeparent = pbuf;
2886 *poffset = parentoffset;
2897 Assert(parentoffset == maxoff);
2915 *topparent = parent;
2940 subtreeparent, poffset,
2941 topparent, topparentrightsib);
2979 maxbufsize =
Min(maxbufsize, INT_MAX);
2981 maxbufsize =
Max(maxbufsize, vstate->
bufsize);
3017#ifdef DEBUG_BTREE_PENDING_FSM
3074#ifdef USE_ASSERT_CHECKING
3103 int newbufsize = vstate->
bufsize * 2;
#define InvalidBlockNumber
static bool BlockNumberIsValid(BlockNumber blockNumber)
BlockNumber BufferGetBlockNumber(Buffer buffer)
Buffer ReleaseAndReadBuffer(Buffer buffer, Relation relation, BlockNumber blockNum)
void LockBuffer(Buffer buffer, BufferLockMode mode)
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
bool ConditionalLockBuffer(Buffer buffer)
void ReleaseBuffer(Buffer buffer)
void MarkBufferDirty(Buffer buffer)
void LockBufferForCleanup(Buffer buffer)
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
#define RelationGetNumberOfBlocks(reln)
static Page BufferGetPage(Buffer buffer)
static Size BufferGetPageSize(Buffer buffer)
static bool BufferIsValid(Buffer bufnum)
void PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
bool PageIndexTupleOverwrite(Page page, OffsetNumber offnum, const void *newtup, Size newsize)
void PageIndexTupleDelete(Page page, OffsetNumber offnum)
void PageInit(Page page, Size pageSize, Size specialSize)
PageHeaderData * PageHeader
static uint16 PageGetSpecialSize(const PageData *page)
static void * PageGetItem(const PageData *page, const ItemIdData *itemId)
static bool PageIsNew(const PageData *page)
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
static void PageSetLSN(Page page, XLogRecPtr lsn)
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
#define PG_USED_FOR_ASSERTS_ONLY
#define MemSet(start, val, len)
int errmsg_internal(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
Assert(PointerIsAligned(start, uint64))
BlockNumber GetFreeIndexPage(Relation rel)
void RecordFreeIndexPage(Relation rel, BlockNumber freeBlock)
IndexTuple CopyIndexTuple(IndexTuple source)
#define INJECTION_POINT(name, arg)
static int pg_cmp_s16(int16 a, int16 b)
int32 ItemPointerCompare(const ItemPointerData *arg1, const ItemPointerData *arg2)
bool ItemPointerEquals(const ItemPointerData *pointer1, const ItemPointerData *pointer2)
IndexTupleData * IndexTuple
struct IndexTupleData IndexTupleData
static Size IndexTupleSize(const IndexTupleData *itup)
#define MaxIndexTuplesPerPage
void * MemoryContextAlloc(MemoryContext context, Size size)
void * repalloc(void *pointer, Size size)
void pfree(void *pointer)
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
#define VALGRIND_CHECK_MEM_IS_DEFINED(addr, size)
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
#define START_CRIT_SECTION()
#define CHECK_FOR_INTERRUPTS()
#define END_CRIT_SECTION()
void _bt_update_posting(BTVacuumPosting vacposting)
Buffer _bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child)
Buffer _bt_relandgetbuf(Relation rel, Buffer obuf, BlockNumber blkno, int access)
static bool _bt_lock_subtree_parent(Relation rel, Relation heaprel, BlockNumber child, BTStack stack, Buffer *subtreeparent, OffsetNumber *poffset, BlockNumber *topparent, BlockNumber *topparentrightsib)
void _bt_upgrademetapage(Page page)
void _bt_relbuf(Relation rel, Buffer buf)
Buffer _bt_gettrueroot(Relation rel)
int _bt_getrootheight(Relation rel)
void _bt_pageinit(Page page, Size size)
static bool _bt_rightsib_halfdeadflag(Relation rel, BlockNumber leafrightsib)
void _bt_pagedel(Relation rel, Buffer leafbuf, BTVacState *vstate)
Buffer _bt_allocbuf(Relation rel, Relation heaprel)
void _bt_delitems_vacuum(Relation rel, Buffer buf, OffsetNumber *deletable, int ndeletable, BTVacuumPosting *updatable, int nupdatable)
static bool _bt_leftsib_splitflag(Relation rel, BlockNumber leftsib, BlockNumber target)
void _bt_checkpage(Relation rel, Buffer buf)
void _bt_metaversion(Relation rel, bool *heapkeyspace, bool *allequalimage)
static BTMetaPageData * _bt_getmeta(Relation rel, Buffer metabuf)
static void _bt_delitems_delete(Relation rel, Buffer buf, TransactionId snapshotConflictHorizon, bool isCatalogRel, OffsetNumber *deletable, int ndeletable, BTVacuumPosting *updatable, int nupdatable)
void _bt_set_cleanup_info(Relation rel, BlockNumber num_delpages)
static bool _bt_mark_page_halfdead(Relation rel, Relation heaprel, Buffer leafbuf, BTStack stack)
bool _bt_conditionallockbuf(Relation rel, Buffer buf)
Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access)
void _bt_unlockbuf(Relation rel, Buffer buf)
void _bt_upgradelockbufcleanup(Relation rel, Buffer buf)
void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level, bool allequalimage)
void _bt_delitems_delete_check(Relation rel, Buffer buf, Relation heapRel, TM_IndexDeleteOp *delstate)
bool _bt_vacuum_needs_cleanup(Relation rel)
static char * _bt_delitems_update(BTVacuumPosting *updatable, int nupdatable, OffsetNumber *updatedoffsets, Size *updatedbuflen, bool needswal)
static int _bt_delitems_cmp(const void *a, const void *b)
void _bt_pendingfsm_finalize(Relation rel, BTVacState *vstate)
void _bt_lockbuf(Relation rel, Buffer buf, int access)
Buffer _bt_getroot(Relation rel, Relation heaprel, int access)
void _bt_pendingfsm_init(Relation rel, BTVacState *vstate, bool cleanuponly)
static void _bt_pendingfsm_add(BTVacState *vstate, BlockNumber target, FullTransactionId safexid)
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf, BlockNumber scanblkno, bool *rightsib_empty, BTVacState *vstate)
#define P_ISHALFDEAD(opaque)
static uint16 BTreeTupleGetNPosting(IndexTuple posting)
static FullTransactionId BTPageGetDeleteXid(Page page)
#define BTREE_MIN_VERSION
static void BTreeTupleSetTopParent(IndexTuple leafhikey, BlockNumber blkno)
#define P_LEFTMOST(opaque)
#define BTPageGetOpaque(page)
#define P_ISDELETED(opaque)
static BlockNumber BTreeTupleGetTopParent(IndexTuple leafhikey)
struct BTPendingFSM BTPendingFSM
static void BTreeTupleSetDownLink(IndexTuple pivot, BlockNumber blkno)
#define P_FIRSTDATAKEY(opaque)
#define P_RIGHTMOST(opaque)
#define P_INCOMPLETE_SPLIT(opaque)
static ItemPointer BTreeTupleGetPostingN(IndexTuple posting, int n)
static bool BTPageIsRecyclable(Page page, Relation heaprel)
static BlockNumber BTreeTupleGetDownLink(IndexTuple pivot)
static ItemPointer BTreeTupleGetMaxHeapTID(IndexTuple itup)
static bool BTreeTupleIsPosting(IndexTuple itup)
static void BTPageSetDeleted(Page page, FullTransactionId safexid)
#define BTREE_NOVAC_VERSION
static ItemPointer BTreeTupleGetHeapTID(IndexTuple itup)
BTStack _bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP, int access)
BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup)
#define SizeOfBtreeVacuum
#define XLOG_BTREE_META_CLEANUP
#define SizeOfBtreeUpdate
#define XLOG_BTREE_VACUUM
#define SizeOfBtreeDelete
#define SizeOfBtreeMarkPageHalfDead
#define XLOG_BTREE_UNLINK_PAGE
#define XLOG_BTREE_UNLINK_PAGE_META
#define SizeOfBtreeNewroot
#define XLOG_BTREE_MARK_PAGE_HALFDEAD
#define XLOG_BTREE_REUSE_PAGE
#define SizeOfBtreeUnlinkPage
#define SizeOfBtreeReusePage
#define XLOG_BTREE_NEWROOT
#define XLOG_BTREE_DELETE
#define InvalidOffsetNumber
#define OffsetNumberIsValid(offsetNumber)
#define OffsetNumberNext(offsetNumber)
#define qsort(a, b, c, d)
void PredicateLockPageCombine(Relation relation, BlockNumber oldblkno, BlockNumber newblkno)
TransactionId GetOldestNonRemovableTransactionId(Relation rel)
bool GlobalVisCheckRemovableFullXid(Relation rel, FullTransactionId fxid)
#define RelationGetRelationName(relation)
#define RelationIsAccessibleInLogicalDecoding(relation)
#define RelationNeedsWAL(relation)
#define RelationUsesLocalBuffers(relation)
void pg_usleep(long microsec)
uint32 btm_last_cleanup_num_delpages
float8 btm_last_cleanup_num_heap_tuples
FullTransactionId safexid
struct BTStackData * bts_parent
IndexBulkDeleteResult * stats
BTPendingFSM * pendingpages
uint16 deletetids[FLEXIBLE_ARRAY_MEMBER]
OffsetNumber updatedoffset
BlockNumber pages_deleted
BlockNumber pages_newly_deleted
MemoryContext rd_indexcxt
RelFileLocator rd_locator
TransactionId snapshotConflictHorizon
FullTransactionId snapshotConflictHorizon
FullTransactionId safexid
BlockNumber leaftopparent
static TransactionId table_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
#define InvalidTransactionId
#define FullTransactionIdFollowsOrEquals(a, b)
FullTransactionId ReadNextFullTransactionId(void)
#define XLogStandbyInfoActive()
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterBufData(uint8 block_id, const void *data, uint32 len)
void XLogRegisterData(const void *data, uint32 len)
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
void XLogBeginInsert(void)