diff --git a/src/gausskernel/storage/access/redo/redo_ubtxlog.cpp b/src/gausskernel/storage/access/redo/redo_ubtxlog.cpp index 74af9091e8c92342e099f09c72ff329fcedd5a39..a21ed52ea2685c94efeb32e27810a64f314d24f4 100644 --- a/src/gausskernel/storage/access/redo/redo_ubtxlog.cpp +++ b/src/gausskernel/storage/access/redo/redo_ubtxlog.cpp @@ -954,6 +954,271 @@ XLogRecParseState *UBTree2XlogFreezeParseBlock(XLogReaderState *record, uint32 * return recordstatehead; } +XLogRecParseState *UBTree3XlogParseInsertInternalBlock(XLogReaderState *record, uint32 *blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + XLogRecParseState *recordstatehead = NULL; + XLogRecParseState *blockstate = NULL; + + *blocknum = 1; + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, UBTREE3_INSERT_PCR_INTERNAL_BLOCK_NUM, recordstatehead); + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, UBTREE3_INSERT_PCR_LEAF_BLOCK_NUM, blockstate); + + if (info == XLOG_UBTREE3_INSERT_PCR_META) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, UBTREE3_INSERT_PCR_META_BLOCK_NUM, blockstate); + } + return recordstatehead; +} + +XLogRecParseState *UBTree3XlogParseInsertBlock(XLogReaderState *record, uint32 *blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + Assert(info == XLOG_UBTREE3_INSERT_PCR || info == XLOG_UBTREE3_DUP_INSERT); + XLogRecParseState *recordstatehead = NULL; + + *blocknum = 1; + + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + + if (ExtremeRedoWorkerIsUndoSpaceWorker()) { + XLogRecSetUBtree3UndoBlockState(record, UBTREE3_UNDO_ORIG_BLOCK_NUM, recordstatehead); + } else { + XLogRecSetBlockDataState(record, UBTREE3_INSERT_PCR_BLOCK_NUM, recordstatehead); + } + + return recordstatehead; +} + +XLogRecParseState *UBTree3XlogParseNewRootBlock(XLogReaderState *record, uint32 *blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + xl_btree_newroot *xlrec = (xl_btree_newroot *)XLogRecGetData(record); + XLogRecParseState *recordstatehead = NULL; + XLogRecParseState *blockstate = NULL; + + *blocknum = 1; + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_NEWROOT_ORIG_BLOCK_NUM, recordstatehead); + + if (xlrec->level > 0) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_NEWROOT_LEFT_BLOCK_NUM, blockstate); + } + + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_NEWROOT_META_BLOCK_NUM, blockstate); + + return recordstatehead; +} + +XLogRecParseState *UBTree3XlogParseDeleteBlock(XLogReaderState *record, uint32 *blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + Assert(info == XLOG_UBTREE3_DELETE_PCR); + XLogRecParseState *recordstatehead = NULL; + + *blocknum = 1; + + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + + if (ExtremeRedoWorkerIsUndoSpaceWorker()) { + XLogRecSetUBtree3UndoBlockState(record, UBTREE3_UNDO_ORIG_BLOCK_NUM, recordstatehead); + } else { + XLogRecSetBlockDataState(record, UBTREE3_DELETE_PCR_BLOCK_NUM, recordstatehead); + } + + return recordstatehead; +} + +XLogRecParseState *UBTree3XlogParseOneBlock(XLogReaderState *record, uint32 blockid, uint32 *blocknum) +{ + XLogRecParseState *recordstatehead = NULL; + + *blocknum = 1; + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + + XLogRecSetBlockDataState(record, blockid, recordstatehead); + + return recordstatehead; +} + +XLogRecParseState *UBTree3XlogParseSplitBlock(XLogReaderState *record, uint32 *blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + Assert(info >= XLOG_UBTREE3_SPLIT_L && XLOG_UBTREE3_SPLIT_R_ROOT); + BlockNumber leftsib = InvalidBlockNumber; + BlockNumber rightsib = InvalidBlockNumber; + BlockNumber rnext = InvalidBlockNumber; + XLogRecParseState *recordstatehead = NULL; + XLogRecParseState *blockstate = NULL; + xl_ubtree3_split *xlrec = (xl_ubtree3_split *)XLogRecGetData(record); + bool isleaf = (xlrec->level == 0); + + XLogRecGetBlockTag(record, BTREE_SPLIT_LEFT_BLOCK_NUM, NULL, NULL, &leftsib); + XLogRecGetBlockTag(record, BTREE_SPLIT_RIGHT_BLOCK_NUM, NULL, NULL, &rightsib); + if (!XLogRecGetBlockTag(record, BTREE_SPLIT_RIGHTNEXT_BLOCK_NUM, NULL, NULL, &rnext)) + rnext = P_NONE; + + *blocknum = 1; + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + + if (xlrec->slotNo != UBTreeInvalidTDSlotId && ExtremeRedoWorkerIsUndoSpaceWorker()) { + XLogRecSetUBtree3UndoBlockState(record, UBTREE3_UNDO_ORIG_BLOCK_NUM, recordstatehead); + return recordstatehead; + } else { + XLogRecSetBlockDataState(record, BTREE_SPLIT_LEFT_BLOCK_NUM, blockstate); + XLogRecSetAuxiBlkNumState(&blockstate->blockparse.extra_rec.blockdatarec, rightsib, InvalidForkNumber); + } + + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_SPLIT_RIGHT_BLOCK_NUM, blockstate); + XLogRecSetAuxiBlkNumState(&blockstate->blockparse.extra_rec.blockdatarec, rnext, leftsib); + + if (rnext != P_NONE) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_SPLIT_RIGHTNEXT_BLOCK_NUM, blockstate); + XLogRecSetAuxiBlkNumState(&blockstate->blockparse.extra_rec.blockdatarec, rightsib, InvalidForkNumber); + } + + if (!isleaf) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_SPLIT_CHILD_BLOCK_NUM, blockstate); + } + + return recordstatehead; +} + +XLogRecParseState *UBTree4XlogUnlinkPageParseBlock(XLogReaderState *record, uint32 *blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + xl_btree_unlink_page *xlrec = (xl_btree_unlink_page *)XLogRecGetData(record); + XLogRecParseState *recordstatehead = NULL; + XLogRecParseState *blockstate = NULL; + + *blocknum = 1; + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + + XLogRecSetBlockDataState(record, BTREE_UNLINK_PAGE_RIGHT_NUM, recordstatehead); + + if (xlrec->leftsib != P_NONE) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_UNLINK_PAGE_LEFT_NUM, blockstate); + } + + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_UNLINK_PAGE_CUR_PAGE_NUM, blockstate); + + if (XLogRecHasBlockRef(record, BTREE_UNLINK_PAGE_CHILD_NUM)) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_UNLINK_PAGE_CHILD_NUM, blockstate); + } + + /* Update metapage if needed */ + if (info == XLOG_UBTREE_UNLINK_PAGE_META) { + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_UNLINK_PAGE_META_NUM, blockstate); + } + + return recordstatehead; +} + +XLogRecParseState *UBTree4XlogMarkHalfDeadParseBlock(XLogReaderState *record, uint32 *blocknum) +{ + XLogRecParseState *recordstatehead = NULL; + XLogRecParseState *blockstate = NULL; + + *blocknum = 1; + XLogParseBufferAllocListFunc(record, &recordstatehead, NULL); + if (recordstatehead == NULL) { + return NULL; + } + + XLogRecSetBlockDataState(record, BTREE_HALF_DEAD_PARENT_PAGE_NUM, recordstatehead); + + (*blocknum)++; + XLogParseBufferAllocListFunc(record, &blockstate, recordstatehead); + if (blockstate == NULL) { + return NULL; + } + XLogRecSetBlockDataState(record, BTREE_HALF_DEAD_LEAF_PAGE_NUM, blockstate); + + return recordstatehead; +} + XLogRecParseState *UBTreeRedoParseToBlock(XLogReaderState *record, uint32 *blocknum) { uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; @@ -1033,6 +1298,91 @@ XLogRecParseState* UBTree2RedoParseToBlock(XLogReaderState* record, uint32* bloc return recordblockstate; } +XLogRecParseState* UBTree3RedoParseToBlock(XLogReaderState* record, uint32* blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + XLogRecParseState *recordblockstate = NULL; + + *blocknum = 0; + switch (info) { + case XLOG_UBTREE3_INSERT_PCR_INTERNAL: + case XLOG_UBTREE3_INSERT_PCR_META: { + recordblockstate = UBTree3XlogParseInsertInternalBlock(record, blocknum); + break; + } + case XLOG_UBTREE3_DUP_INSERT: + case XLOG_UBTREE3_INSERT_PCR: { + recordblockstate = UBTree3XlogParseInsertBlock(record, blocknum); + break; + } + case XLOG_UBTREE3_NEW_ROOT: { + recordblockstate = UBTree3XlogParseNewRootBlock(record, blocknum); + break; + } + case XLOG_UBTREE3_DELETE_PCR: { + recordblockstate = UBTree3XlogParseDeleteBlock(record, blocknum); + break; + } + case XLOG_UBTREE3_PRUNE_PAGE_PCR: { + recordblockstate = UBTree3XlogParseOneBlock(record, UBTREE3_PRUNE_PAGE_PCR_BLOCK_NUM, blocknum); + break; + } + case XLOG_UBTREE3_FREEZE_TD_SLOT: { + recordblockstate = UBTree3XlogParseOneBlock(record, UBTREE3_FREEZE_TD_SLOT_BLOCK_NUM, blocknum); + break; + } + case XLOG_UBTREE3_REUSE_TD_SLOT: { + recordblockstate = UBTree3XlogParseOneBlock(record, UBTREE3_REUSE_TD_SLOT_BLOCK_NUM, blocknum); + break; + } + case XLOG_UBTREE3_EXTEND_TD_SLOTS: { + recordblockstate = UBTree3XlogParseOneBlock(record, UBTREE3_EXTEND_TD_SLOTS_BLOCK_NUM, blocknum); + break; + } + case XLOG_UBTREE3_ROLLBACK_TXN: { + recordblockstate = UBTree3XlogParseOneBlock(record, UBTREE3_ROLLBACK_TXN_BLOCK_NUM, blocknum); + break; + } + case XLOG_UBTREE3_SPLIT_L: + case XLOG_UBTREE3_SPLIT_L_ROOT: + case XLOG_UBTREE3_SPLIT_R: + case XLOG_UBTREE3_SPLIT_R_ROOT: { + recordblockstate = UBTree3XlogParseSplitBlock(record, blocknum); + break; + } + default: + ereport(PANIC, (errmsg("UBTree3RedoParseToBlock: unknown op code %u", info))); + } + + return recordblockstate; +} + +XLogRecParseState* UBTree4RedoParseToBlock(XLogReaderState* record, uint32* blocknum) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + XLogRecParseState *recordblockstate = NULL; + + *blocknum = 0; + switch (info) { + case XLOG_UBTREE4_UNLINK_PAGE: { + recordblockstate = UBTree4XlogUnlinkPageParseBlock(record, blocknum); + break; + } + case XLOG_UBTREE4_UNLINK_PAGE_META: { + recordblockstate = UBTree4XlogUnlinkPageParseBlock(record, blocknum); + break; + } + case XLOG_UBTREE4_MARK_PAGE_HALFDEAD: { + recordblockstate = UBTree4XlogMarkHalfDeadParseBlock(record, blocknum); + break; + } + default: + ereport(PANIC, (errmsg("UBTree4RedoParseToBlock: unknown op code %u", info))); + } +} + static void UBTreeXlogInsertBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) { @@ -1796,6 +2146,331 @@ void UBTree4XlogHalfdeadPageOperatorLeafpage(RedoBufferInfo *lbuf, void *recordd PageSetLSN(lbuf->pageinfo.page, lbuf->lsn); } +static void UBTree3XlogInsertPcrInternalBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, + RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + uint8 block = XLogBlockDataGetBlockId(datadecode); + if (action == BLK_NEEDS_REDO) { + Size datalen; + char *blkdata = XLogBlockDataGetBlockData(datadecode, &datalen); + if (block == UBTREE3_INSERT_PCR_INTERNAL_BLOCK_NUM) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + xl_btree_insert *xlrec = (xl_btree_insert *)maindata; + Page page = bufferinfo->pageinfo.page; + + if (UBTPCRPageAddItem(page, (Item)blkdata, datalen, xlrec->offnum, false) == InvalidOffsetNumber) { + ereport(PANIC, (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("faild to add left P_HIKEY wihle redo."))); + } + PageSetLSN(page, bufferinfo->lsn); + } else if (block == UBTREE3_INSERT_PCR_META_BLOCK_NUM) { + UBTree3RestoreMetaOperatorPage(bufferinfo, (void *)blkdata, datalen); + } else { + UBTreeXlogClearIncompleteSplit(bufferinfo); + } + MakeRedoBufferDirty(bufferinfo); + } + + return; +} + +static void UBTree3XlogInsertBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, + RedoBufferInfo *bufferinfo, bool isDup) +{ + XLogBlockDataParse *datadecode = blockdatarec; + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + xl_ubtree3_insert_or_delete *xlrec = (xl_ubtree3_insert_or_delete *)maindata; + char *recordptr = (char *)xlrec; + recordptr += SizeOfUbtree3InsertOrDelete; + IndexTuple itup = (IndexTuple)recordptr; + recordptr += IndexTupleSize(itup); + UndoRecPtr urec = ((XlUndoHeader *)recordptr)->urecptr; + Page page = bufferinfo->pageinfo.page; + if (!isDup) { + Size size = MAXALIGN(IndexTupleSize(itup)); + if (!UBTreePCRPageAddTuple(page, size, NULL, itup, xlrec->offNum, false, xlrec->tdId)) { + ereport(ERROR, (errcode(ERRCODE_INDEX_CORRUPTED), errmsg("failed to add new item to block"))); + } + } + UBTreeItemId iid = UBTreePCRGetRowPtr(page, xlrec->offNum); + UBTPCRPageOpaque opaque = (UBTPCRPageOpaque)PageGetSpecialPointer(page); + UBTreeTD td = UBTreePCRGetTD(page, xlrec->tdId); + opaque->activeTupleCount ++; + td->setInfo(xlrec->curXid, urec); + if (isDup) { + iid->lp_flags = LP_NORMAL; + UBTreePCRSetIndexTupleTDSlot(iid, xlrec->tdId); + UBTreePCRClearIndexTupleTDInvalid(iid); + UBTreePCRClearIndexTupleDeleted(iid); + } + PageSetLSN(page, bufferinfo->lsn); + MakeRedoBufferDirty(bufferinfo); + } + + return; +} + +static void UBTree3XlogNewRootBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + Size dataLen; + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + char *blkdata = XLogBlockDataGetBlockData(datadecode, &dataLen); + uint8 blockId = XLogBlockDataGetBlockId(datadecode); + + if (action != BLK_NEEDS_REDO) { + return; + } + if (blockId == BTREE_NEWROOT_ORIG_BLOCK_NUM) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + xl_btree_newroot *xlrec = (xl_btree_newroot *)maindata; + Page page = bufferinfo->pageinfo.page; + UBTreePCRPageInit(page, bufferinfo->pageinfo.pagesize); + UBTPCRPageOpaque opaque = (UBTPCRPageOpaque)PageGetSpecialPointer(page); + opaque->btpo_cycleid = 0; + opaque->btpo.level = xlrec->level; + opaque->btpo_flags = BTP_ROOT; + if (xlrec->level == 0) { + opaque->btpo_flags |= BTP_LEAF; + UBTreePCRInitTD(page); + } else { + opaque->td_count = 0; + Item lItem = (Item)maindata; + Size lItemSz = IndexTupleSize(lItem); + Item rItem = (Item)(maindata + lItemSz); + Size rItemSz = IndexTupleSize(rItem); + + if (UBTPCRPageAddItem(page, lItem, lItemSz, P_HIKEY, false) == InvalidOffsetNumber) { + ereport(PANIC, (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("faild to add left P_HIKEY wihle redo."))); + } + if (UBTPCRPageAddItem(page, rItem, rItemSz, P_FIRSTKEY, false) == InvalidOffsetNumber) { + ereport(PANIC, (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("faild to add left P_FIRSTKEY wihle redo."))); + } + PageSetLSN(page, bufferinfo->lsn); + } + } else if (blockId == BTREE_NEWROOT_META_BLOCK_NUM) { + UBTree3RestoreMetaOperatorPage(bufferinfo, (void *)blkdata, dataLen); + } else { + if (XLogCheckBlockDataRedoAction(datadecode, bufferinfo) == BLK_NEEDS_REDO) { + UBTreeXlogClearIncompleteSplit(bufferinfo); + } + } + MakeRedoBufferDirty(bufferinfo); + + return; +} + +static void UBTree3XlogDeleteBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + Size dataLen; + if (XLogCheckBlockDataRedoAction(datadecode, bufferinfo) == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + char *recptr = maindata; + xl_btree_newroot *xlrec = (xl_btree_newroot *)recptr; + recptr += SizeOfUbtree3InsertOrDelete; + XlUndoHeader *xlundohdr = (XlUndoHeader *)((char *)xlrec + SizeOfUbtree3InsertOrDelete); + UBTree3XlogDeleteOperatorPage(bufferinfo, maindata, xlundohdr->urecptr); + } + MakeRedoBufferDirty(bufferinfo); + + return; +} + +static void UBTree3XlogFreezeTdSlotBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + + if (XLogBlockDataGetBlockId(datadecode) == UBTREE3_FREEZE_TD_SLOT_BLOCK_NUM) { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + UBTree3XlogPrunePageOperatorPage(bufferinfo, (void*)maindata, bufferinfo->blockinfo.rnode.relNode); + MakeRedoBufferDirty(bufferinfo); + } + } + return; +} + +static void UBTree3XlogExtendTdSlotsBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + + if (XLogBlockDataGetBlockId(datadecode) == UBTREE3_EXTEND_TD_SLOTS_BLOCK_NUM) { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + UBTree3XlogPrunePageOperatorPage(bufferinfo, (void*)maindata, bufferinfo->blockinfo.rnode.relNode); + MakeRedoBufferDirty(bufferinfo); + } + } + return; +} + +static void UBTree3XlogPrunePageBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + + if (XLogBlockDataGetBlockId(datadecode) == UBTREE3_PRUNE_PAGE_PCR_BLOCK_NUM) { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + UBTree3XlogPrunePageOperatorPage(bufferinfo, (void*)maindata, bufferinfo->blockinfo.rnode.relNode); + MakeRedoBufferDirty(bufferinfo); + } + } +} + +static void UBTree3XlogReuseTdSlotBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + + if (XLogBlockDataGetBlockId(datadecode) == UBTREE3_REUSE_TD_SLOT_BLOCK_NUM) { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + UBTree3XlogReuseTdOperatorPage(bufferinfo, (void*)maindata); + MakeRedoBufferDirty(bufferinfo); + } + } +} + +static void UBTree3XlogRollBackTxnBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + + if (XLogBlockDataGetBlockId(datadecode) == UBTREE3_ROLLBACK_TXN_BLOCK_NUM) { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + UBTree3XlogRollbackTxnOperatorPage(bufferinfo, (void*)maindata); + MakeRedoBufferDirty(bufferinfo); + } + } +} + +static void UBTree3XlogSplitBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + uint8 info = (XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK) & XLOG_UBTREE_PCR_OP_MASK; + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + if (XLogBlockDataGetBlockId(datadecode) == BTREE_SPLIT_RIGHT_BLOCK_NUM) { + Size dataLen; + Page rpage = bufferinfo->pageinfo.page; + xl_ubtree3_split *xlrec = (xl_ubtree3_split *)maindata; + char * blkdata = XLogBlockDataGetBlockData(datadecode, &dataLen); + UBTreePCRPageInit(rpage, bufferinfo->pageinfo.pagesize); + errno_t rc = memcpy_s(rpage, xlrec->rightLower, blkdata, xlrec->rightLower); + securec_check(rc, "\0", "\0"); + blkdata += xlrec->rightLower; + Size upper = dataLen - xlrec->rightLower; + rc = memcpy_s(rpage + BLCKSZ - upper, upper, blkdata, upper); + securec_check(rc, "\0", "\0"); + PageSetLSN(rpage, bufferinfo->lsn); + MakeRedoBufferDirty(bufferinfo); + } else { + if (XLogCheckBlockDataRedoAction(datadecode, bufferinfo) == BLK_NEEDS_REDO) { + if (XLogBlockDataGetBlockId(datadecode) == BTREE_SPLIT_LEFT_BLOCK_NUM) { + Size datalen; + char *blkdata = XLogBlockDataGetBlockData(datadecode, &datalen); + bool onleft = ((info == XLOG_UBTREE3_SPLIT_L) || (info == XLOG_UBTREE3_SPLIT_L_ROOT)); + BTree3XlogSplitLeftPage(bufferinfo, (void *)maindata, onleft, (void *)blkdata, datalen); + } else if (XLogBlockDataGetBlockId(datadecode) == BTREE_SPLIT_RIGHTNEXT_BLOCK_NUM) { + Page page = bufferinfo->pageinfo.page; + UBTPCRPageOpaque opaque = (UBTPCRPageOpaque)PageGetSpecialPointer(page); + opaque->btpo_prev = XLogBlockDataGetAuxiBlock1(datadecode); + PageSetLSN(page, bufferinfo->lsn); + } else { + Assert(XLogBlockDataGetBlockId(datadecode) == BTREE_SPLIT_CHILD_BLOCK_NUM); + Page page = bufferinfo->pageinfo.page; + UBTPCRPageOpaque opaque = (UBTPCRPageOpaque)PageGetSpecialPointer(page); + opaque->btpo_flags &= ~BTP_INCOMPLETE_SPLIT; + PageSetLSN(page, bufferinfo->lsn); + } + MakeRedoBufferDirty(bufferinfo); + } + } + + return; +} + +static void UBTree4XlogUnlinkPageBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + uint8 block_id = XLogBlockDataGetBlockId(datadecode); + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + + if (block_id == BTREE_UNLINK_PAGE_CUR_PAGE_NUM) { + UBTree4XlogUnlinkPageOperatorCurpage(bufferinfo, (void *)maindata); + MakeRedoBufferDirty(bufferinfo); + } else if (block_id == BTREE_UNLINK_PAGE_META_NUM) { + Size blkdatalen; + char *blkdata = NULL; + + blkdata = XLogBlockDataGetBlockData(datadecode, &blkdatalen); + + UBTree3RestoreMetaOperatorPage(bufferinfo, (void *)blkdata, blkdatalen); + MakeRedoBufferDirty(bufferinfo); + } else if (block_id == BTREE_UNLINK_PAGE_CHILD_NUM) { + UBTreeXlogUnlinkPageOperatorChildpage(bufferinfo, (void *)maindata); + MakeRedoBufferDirty(bufferinfo); + } else { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + if (block_id == BTREE_UNLINK_PAGE_RIGHT_NUM) { + UBTree4XlogUnlinkPageOperatorChildpage(bufferinfo, (void *)maindata); + } else { + UBTree4XlogUnlinkPageOperatorLeftpage(bufferinfo, (void *)maindata); + } + MakeRedoBufferDirty(bufferinfo); + } + } + +} + +static void UBTree4XlogMarkPageHalfDeadBlock( + XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo) +{ + XLogBlockDataParse *datadecode = blockdatarec; + uint8 block_id = XLogBlockDataGetBlockId(datadecode); + char *maindata = XLogBlockDataGetMainData(datadecode, NULL); + + if (block_id == BTREE_HALF_DEAD_LEAF_PAGE_NUM) { + bool willinit = XLogBlockDataGetBlockFlags(blockdatarec) & BKPBLOCK_WILL_INIT; + if (willinit) { + UBTree4XlogHalfdeadPageOperatorLeafpage(bufferinfo, (void *)maindata, willinit); + MakeRedoBufferDirty(bufferinfo); + return; + } + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + UBTree4XlogHalfdeadPageOperatorLeafpage(bufferinfo, (void *)maindata, willinit); + MakeRedoBufferDirty(bufferinfo); + } + } else { + XLogRedoAction action = XLogCheckBlockDataRedoAction(datadecode, bufferinfo); + if (action == BLK_NEEDS_REDO) { + UBTree4XlogHalfdeadPageOperatorParentpage(bufferinfo, (void *)maindata); + MakeRedoBufferDirty(bufferinfo); + } + } +} + void UBTree2RedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdatarec, RedoBufferInfo* bufferinfo) { uint8 info = XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK; @@ -1821,6 +2496,74 @@ void UBTree2RedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdat } } +void UBTree3RedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdatarec, RedoBufferInfo* bufferinfo) +{ + uint8 info = XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + + switch (info) { + case XLOG_UBTREE3_INSERT_PCR_INTERNAL: + case XLOG_UBTREE3_INSERT_PCR_META: + UBTree3XlogInsertPcrInternalBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_DUP_INSERT: + UBTree3XlogInsertBlock(blockhead, blockdatarec, bufferinfo, true); + break; + case XLOG_UBTREE3_INSERT_PCR: + UBTree3XlogInsertBlock(blockhead, blockdatarec, bufferinfo, false); + break; + case XLOG_UBTREE3_NEW_ROOT: + UBTree3XlogNewRootBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_DELETE_PCR: + UBTree3XlogDeleteBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_PRUNE_PAGE_PCR: + UBTree3XlogPrunePageBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_FREEZE_TD_SLOT: + UBTree3XlogFreezeTdSlotBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_REUSE_TD_SLOT: + UBTree3XlogReuseTdSlotBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_EXTEND_TD_SLOTS: + UBTree3XlogExtendTdSlotsBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_ROLLBACK_TXN: + UBTree3XlogRollBackTxnBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE3_SPLIT_L: + case XLOG_UBTREE3_SPLIT_R: + case XLOG_UBTREE3_SPLIT_L_ROOT: + case XLOG_UBTREE3_SPLIT_R_ROOT: + UBTree3XlogSplitBlock(blockhead, blockdatarec, bufferinfo); + break; + default: + ereport(PANIC, (errmsg("UBTree3RedoDataBlock: unknown op code %hhu", info))); + } +} + +void UBTree4RedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdatarec, RedoBufferInfo* bufferinfo) +{ + uint8 info = XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + + switch (info) { + case XLOG_UBTREE4_UNLINK_PAGE: + UBTree4XlogUnlinkPageBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE4_UNLINK_PAGE_META: + UBTree4XlogUnlinkPageBlock(blockhead, blockdatarec, bufferinfo); + break; + case XLOG_UBTREE4_MARK_PAGE_HALFDEAD: + UBTree4XlogMarkPageHalfDeadBlock(blockhead, blockdatarec, bufferinfo); + break; + default: + ereport(PANIC, (errmsg("UBTree4RedoDataBlock: unknown op code %hhu", info))); + } +} + void UBTreeRedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdatarec, RedoBufferInfo* bufferinfo) { uint8 info = XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK; diff --git a/src/gausskernel/storage/access/redo/redo_xlogutils.cpp b/src/gausskernel/storage/access/redo/redo_xlogutils.cpp index b2d669501e697c183434c0d27ded7c8b943a723b..9e6682c44b744cdd336c3ac7cdbe0ab421cbeff3 100644 --- a/src/gausskernel/storage/access/redo/redo_xlogutils.cpp +++ b/src/gausskernel/storage/access/redo/redo_xlogutils.cpp @@ -1282,6 +1282,110 @@ void XLogParseBufferRelease(XLogRecParseState *recordstate) XLogMemRelease(memctl, descstate->buff_id); } +void GetUBtree3XlUndoHeaderExtraData(char **currLogPtr, XlUndoHeaderExtra *xlundohdrextra, uint8 flag) +{ + xlundohdrextra->size = 0; + + if ((flag & UBTREE_XLOG_HAS_BLK_PREV) != 0) { + xlundohdrextra->blkprev = *((UndoRecPtr *)*currLogPtr); + xlundohdrextra->size += sizeof(UndoRecPtr); + *currLogPtr += sizeof(UndoRecPtr); + } else { + xlundohdrextra->blkprev = INVALID_UNDO_REC_PTR; + } + + if ((flag & UBTREE_XLOG_HAS_XACT_PREV) != 0) { + xlundohdrextra->prevurp = *((UndoRecPtr *)*currLogPtr); + xlundohdrextra->size += sizeof(UndoRecPtr); + *currLogPtr += sizeof(UndoRecPtr); + } else { + xlundohdrextra->prevurp = INVALID_UNDO_REC_PTR; + } + + if ((flag & UBTREE_XLOG_HAS_PARTITION_OID) != 0) { + xlundohdrextra->partitionOid = *((Oid *)*currLogPtr); + xlundohdrextra->size += sizeof(Oid); + *currLogPtr += sizeof(Oid); + } else { + xlundohdrextra->partitionOid = INVALID_UNDO_REC_PTR; + } +} + +RelFileNode XLogRecSetUBtree3UndoInternalBlockState(XLogReaderState *record, + char *recordPtr, XLogBlockUndoParse *blockundo, DecodedBkpBlock *decodebkp) +{ + RelFileNode rnode; + xl_ubtree3_insert_or_delete *xlrec = (xl_ubtree3_insert_or_delete *)recordPtr; + recordPtr += SizeOfUbtree3InsertOrDelete; + IndexTuple itup = (IndexTuple)recordPtr; + const Size tupleSize = IndexTupleSize(itup); + recordPtr += tupleSize; + blockundo->maindata = (char *)itup; + blockundo->recordlen = tupleSize; + XlUndoHeader *xlundohdr = (XlUndoHeader *)recordPtr; + recordPtr += SizeOfXLUndoHeader; + UBTreeUndoInfo uinfo = (UBTreeUndoInfo)recordPtr; + recordPtr += SizeOfUBTreeUndoInfoData; + + ubtree3UndoParse *parseBlock = &blockundo->ubtree3UndoParse; + GetUBtree3XlUndoHeaderExtraData(&recordPtr, &parseBlock->xlundohdrextra, xlundohdr->flag); + undo::XlogUndoMeta *xlundometa = (undo::XlogUndoMeta *)recordPtr; + + parseBlock->recxid = XLogRecGetXid(record); + parseBlock->offnum = xlrec->offNum; + parseBlock->prevXidOfTuple = xlrec->prevXidOfTuple; + parseBlock->blkno = decodebkp->blkno; + parseBlock->spcNode = decodebkp->rnode.spcNode; + parseBlock->relNode = decodebkp->rnode.relNode; + parseBlock->lsn = record->EndRecPtr; + parseBlock->xlundohdr.urecptr = xlundohdr->urecptr; + parseBlock->xlundohdr.relOid = xlundohdr->relOid; + parseBlock->uinfo = uinfo; + + undo::CopyUndoMeta(*xlundometa, parseBlock->xlundometa); + UNDO_PTR_ASSIGN_REL_FILE_NODE(rnode, xlundohdr->urecptr, UNDO_DB_OID); + + return rnode; +} + +void XLogRecSetUBtree3UndoBlockState(XLogReaderState *record, uint32 blockid, XLogRecParseState *undostate) +{ + char *xlrec = (char *)XLogRecGetData(record); + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + RelFileNode rnode; + + Assert(XLogRecHasBlockRef(record, blockid)); + DecodedBkpBlock *decodebkp = &(record->blocks[blockid]); + + XLogBlockUndoParse *blockundo = &(undostate->blockparse.extra_rec.blockundorec); + + switch (info) { + case XLOG_UBTREE3_DUP_INSERT: + case XLOG_UBTREE3_INSERT_PCR: + case XLOG_UBTREE3_DELETE_PCR: { + rnode = XLogRecSetUBtree3UndoInternalBlockState(record, xlrec, + blockundo, decodebkp); + break; + } + case XLOG_UBTREE3_SPLIT_L: + case XLOG_UBTREE3_SPLIT_L_ROOT: + case XLOG_UBTREE3_SPLIT_R: + case XLOG_UBTREE3_SPLIT_R_ROOT: { + Assert(((xl_ubtree3_split *)xlrec)->slotNo != UBTreeInvalidTDSlotId); + xlrec += SizeOfUbtree3Split; + rnode = XLogRecSetUBtree3UndoInternalBlockState(record, xlrec, + blockundo, decodebkp); + break; + } + default: + ereport(PANIC, (errmsg("XLogRecSetUBtree3UndoBlockState: unknown op code %u", (uint8)info))); + } + + RelFileNodeForkNum filenode = RelFileNodeForkNumFill(&rnode, InvalidBackendId, UNDO_FORKNUM, InvalidBlockNumber); + XLogRecSetBlockCommonState(record, BLOCK_DATA_UNDO_TYPE, filenode, undostate); +} + void XLogBlockDataCommonRedo(XLogBlockHead *blockhead, void *blockrecbody, RedoBufferInfo *bufferinfo) { if (XLogBlockHeadGetValidInfo(blockhead) != BLOCK_DATA_MAIN_DATA_TYPE) { @@ -1308,6 +1412,12 @@ void XLogBlockDataCommonRedo(XLogBlockHead *blockhead, void *blockrecbody, RedoB case RM_UBTREE2_ID: UBTree2RedoDataBlock(blockhead, blockdatarec, bufferinfo); break; + case RM_UBTREE3_ID: + UBTree3RedoDataBlock(blockhead, blockdatarec, bufferinfo); + break; + case RM_UBTREE4_ID: + UBTree4RedoDataBlock(blockhead, blockdatarec, bufferinfo); + break; case RM_HASH_ID: HashRedoDataBlock(blockhead, blockdatarec, bufferinfo); break; @@ -1385,6 +1495,9 @@ void XLogBlockUndoCommonRedo(XLogBlockHead *blockhead, void *blockrecbody, RedoB case RM_UNDOACTION_ID: RedoRollbackFinishBlock(blockhead, blockundorec, bufferinfo); break; + case RM_UBTREE3_ID: + RedoUbtree3UndoBlock(blockhead, blockundorec, bufferinfo); + break; default: ereport(PANIC, (errmsg("XLogBlockUndoCommonRedo: unknown rmid %u", rmid))); } @@ -1985,6 +2098,8 @@ static const XLogParseBlock g_xlogParseBlockTable[RM_MAX_ID + 1] = { { UHeapRollbackFinishRedoParseToBlock, RM_UNDOACTION_ID}, { UBTreeRedoParseToBlock, RM_UBTREE_ID }, { UBTree2RedoParseToBlock, RM_UBTREE2_ID }, + { UBTree3RedoParseToBlock, RM_UBTREE3_ID }, + { UBTree4RedoParseToBlock, RM_UBTREE4_ID }, { segpage_redo_parse_to_block, RM_SEGPAGE_ID }, { NULL, RM_REPLORIGIN_ID }, { NULL, RM_COMPRESSION_REL_ID }, diff --git a/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp b/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp index 56039e5c6e648e57bbdd7a56a188c69fba2f8644..45081e6886b4eed89fc9a3f18620b2ef34712154 100755 --- a/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp +++ b/src/gausskernel/storage/access/transam/extreme_rto/dispatcher.cpp @@ -114,6 +114,7 @@ static void AddSlotToPLSet(uint32); static void **CollectStatesFromWorkers(GetStateFunc); static void GetSlotIds(XLogReaderState *record); static void GetUndoSlotIds(XLogReaderState *record); +static void UBTree3GetUndoSlotIds(XLogReaderState *record); STATIC LogDispatcher *CreateDispatcher(); static void DestroyRecoveryWorkers(); static void SSDestroyRecoveryWorkers(); @@ -161,6 +162,10 @@ static bool DispatchUBTree2Record(XLogReaderState* record, List* expectedTLIs, T static bool RmgrRecordInfoValid(XLogReaderState *record, uint8 minInfo, uint8 maxInfo); static bool RmgrGistRecordInfoValid(XLogReaderState *record, uint8 minInfo, uint8 maxInfo); +/* ustore pcr */ +static bool DispatchUBTree3Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); +static bool DispatchUBTree4Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); + /* Ustore table */ static bool DispatchUHeapRecord(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); static bool DispatchUHeap2Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); @@ -227,6 +232,10 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchLogicalDDLMsgRecord, RmgrRecordInfoValid, RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE, XLOG_LOGICAL_DDL_MESSAGE }, { DispatchGenericRecord, RmgrRecordInfoValid, RM_GENERIC_ID, XLOG_GENERIC_LOG, XLOG_GENERIC_LOG }, + { DispatchUBTree3Record, RmgrRecordInfoValid, RM_UBTREE3_ID, XLOG_UBTREE3_INSERT_PCR_INTERNAL, + XLOG_UBTREE3_INSERT_PCR_META }, + { DispatchUBTree4Record, RmgrRecordInfoValid, RM_UBTREE4_ID, XLOG_UBTREE4_UNLINK_PAGE, + XLOG_UBTREE4_MARK_PAGE_HALFDEAD }, }; const int REDO_WAIT_SLEEP_TIME = 5000; /* 5ms */ @@ -814,6 +823,11 @@ static bool RmgrRecordInfoValid(XLogReaderState *record, uint8 minInfo, uint8 ma info = (info & XLOG_UHEAP_OPMASK); break; } + case RM_UBTREE3_ID: + case RM_UBTREE4_ID: { + info = (info & XLOG_UBTREE_PCR_OP_MASK); + break; + } default: break; } @@ -1395,6 +1409,31 @@ static bool DispatchUBTree2Record(XLogReaderState* record, List* expectedTLIs, T return false; } +static bool DispatchUBTree3Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime) +{ + GetSlotIds(record); + UBTree3GetUndoSlotIds(record); + + RedoItem *item = GetRedoItemPtr(record); + ReferenceRedoItem(item); + for (uint32 i = 0; i < g_dispatcher->pageLineNum; i++) { + if (g_dispatcher->chosedPageLineIds[i] > 0) { + ReferenceRedoItem(item); + AddPageRedoItem(g_dispatcher->pageLines[i].batchThd, item); + elog(DEBUG1, "Dispatch page worker %d", i); + } + } + DereferenceRedoItem(item); + + return false; +} + +static bool DispatchUBTree4Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime) +{ + DispatchRecordWithPages(record, expectedTLIs); + return false; +} + /* Run from the dispatcher thread. */ static bool DispatchGinRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) { @@ -1638,6 +1677,57 @@ static void GetUndoSlotIds(XLogReaderState *record) AddSlotToPLSet(undoSlotId); } +static void UBTree3GetUndoSlotIds(XLogReaderState *record) +{ + uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; + uint8 op = info &= XLOG_UBTREE_PCR_OP_MASK; + int size = 0; + char *recordPtr = (char *)XLogRecGetData(record); + + switch (op) { + case XLOG_UBTREE3_INSERT_PCR_INTERNAL: + case XLOG_UBTREE3_PRUNE_PAGE_PCR: + case XLOG_UBTREE3_FREEZE_TD_SLOT: + case XLOG_UBTREE3_REUSE_TD_SLOT: + case XLOG_UBTREE3_EXTEND_TD_SLOTS: + case XLOG_UBTREE3_NEW_ROOT: + case XLOG_UBTREE3_INSERT_PCR_META: + case XLOG_UBTREE3_ROLLBACK_TXN: + return; + case XLOG_UBTREE3_DUP_INSERT: + case XLOG_UBTREE3_INSERT_PCR: + case XLOG_UBTREE3_DELETE_PCR: { + recordPtr += SizeOfUbtree3InsertOrDelete; + IndexTuple itup = (IndexTuple)recordPtr; + size = SizeOfUbtree3InsertOrDelete + IndexTupleSize(itup); + break; + } + case XLOG_UBTREE3_SPLIT_L: + case XLOG_UBTREE3_SPLIT_R: + case XLOG_UBTREE3_SPLIT_L_ROOT: + case XLOG_UBTREE3_SPLIT_R_ROOT: { + xl_ubtree3_split *xlrec = (xl_ubtree3_split *)recordPtr; + if (xlrec->slotNo == UBTreeInvalidTDSlotId) { + /* split internal node without undo data. */ + return; + } + recordPtr += SizeOfUbtree3Split + SizeOfUbtree3InsertOrDelete; + IndexTuple itup = (IndexTuple)recordPtr; + size = SizeOfUbtree3Split + SizeOfUbtree3InsertOrDelete + IndexTupleSize(itup); + break; + } + default: + ereport(ERROR, (errmsg("Invalid op in UBTree3GetUndoSlotIds"))); + } + /* Get slot id for undo zone */ + char *newXlrec = XLogRecGetData(record); + XlUndoHeader *xlundohdr = (XlUndoHeader *)(newXlrec + size); + int zoneid = UNDO_PTR_GET_ZONE_ID(xlundohdr->urecptr); + uint32 undoSlotId = GetUndoSpaceWorkerId(zoneid); + + AddSlotToPLSet(undoSlotId); +} + static void AddSlotToPLSet(uint32 id) { if (id >= g_dispatcher->pageLineNum) { diff --git a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp index e07f58120ef0094ea7efadc2ef50ad7142b367bf..df8b7d6a29253c2acf51cbf03451a2a1877105d6 100644 --- a/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp +++ b/src/gausskernel/storage/access/transam/ondemand_extreme_rto/dispatcher.cpp @@ -163,6 +163,8 @@ static bool DispatchSegpageSmgrRecord(XLogReaderState *record, List *expectedTLI static bool DispatchRepOriginRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static bool DispatchUBTreeRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); +static bool DispatchUBTree3Record(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); +static bool DispatchUBTree4Record(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime); static bool DispatchUBTree2Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime); static bool RmgrRecordInfoValid(XLogReaderState *record, uint8 minInfo, uint8 maxInfo); static bool RmgrGistRecordInfoValid(XLogReaderState *record, uint8 minInfo, uint8 maxInfo); @@ -231,6 +233,10 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchLogicalDDLMsgRecord, RmgrRecordInfoValid, RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE, XLOG_LOGICAL_DDL_MESSAGE }, { DispatchGenericRecord, RmgrRecordInfoValid, RM_GENERIC_ID, XLOG_GENERIC_LOG, XLOG_GENERIC_LOG }, + { DispatchUBTree3Record, RmgrRecordInfoValid, RM_UBTREE3_ID, XLOG_UBTREE3_INSERT_PCR_INTERNAL, + XLOG_UBTREE3_INSERT_PCR_META }, + { DispatchUBTree4Record, RmgrRecordInfoValid, RM_UBTREE4_ID, XLOG_UBTREE4_UNLINK_PAGE, + XLOG_UBTREE4_MARK_PAGE_HALFDEAD }, }; const int REDO_WAIT_SLEEP_TIME = 5000; /* 5ms */ @@ -816,6 +822,11 @@ static bool RmgrRecordInfoValid(XLogReaderState *record, uint8 minInfo, uint8 ma info = (info & XLOG_UHEAP_OPMASK); break; } + case RM_UBTREE3_ID: + case RM_UBTREE4_ID: { + info = (info & XLOG_UBTREE_PCR_OP_MASK); + break; + } default: break; } @@ -1340,6 +1351,18 @@ static bool DispatchUBTree2Record(XLogReaderState* record, List* expectedTLIs, T return false; } +static bool DispatchUBTree3Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime) +{ + /* pcr not currently support ondemand extreme_rto */ + return false; +} + +static bool DispatchUBTree4Record(XLogReaderState* record, List* expectedTLIs, TimestampTz recordXTime) +{ + /* pcr not currently support ondemand extreme_rto */ + return false; +} + /* Run from the dispatcher thread. */ static bool DispatchGinRecord(XLogReaderState *record, List *expectedTLIs, TimestampTz recordXTime) { diff --git a/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp b/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp index eaf1e53e736f6a9b80745a72f6d45e6c1ba0158e..63b8f3301fbd2f07ac2c2bcbe7c93a0160436e6a 100755 --- a/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp +++ b/src/gausskernel/storage/access/transam/parallel_recovery/dispatcher.cpp @@ -232,10 +232,6 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchUBTreeRecord, RmgrRecordInfoValid, RM_UBTREE_ID, XLOG_UBTREE_INSERT_LEAF, XLOG_UBTREE_PRUNE_PAGE}, { DispatchUBTree2Record, RmgrRecordInfoValid, RM_UBTREE2_ID, XLOG_UBTREE2_SHIFT_BASE, XLOG_UBTREE2_FREEZE }, - { DispatchUBTree3Record, RmgrRecordInfoValid, RM_UBTREE3_ID, XLOG_UBTREE3_INSERT_PCR_INTERNAL, - XLOG_UBTREE3_INSERT_PCR_META }, - { DispatchUBTree4Record, RmgrRecordInfoValid, RM_UBTREE4_ID, XLOG_UBTREE4_UNLINK_PAGE, - XLOG_UBTREE4_MARK_PAGE_HALFDEAD }, { DispatchSegpageSmgrRecord, RmgrRecordInfoValid, RM_SEGPAGE_ID, XLOG_SEG_ATOMIC_OPERATION, XLOG_SEG_NEW_PAGE }, { DispatchRepOriginRecord, RmgrRecordInfoValid, RM_REPLORIGIN_ID, XLOG_REPLORIGIN_SET, XLOG_REPLORIGIN_DROP }, @@ -244,6 +240,10 @@ static const RmgrDispatchData g_dispatchTable[RM_MAX_ID + 1] = { { DispatchLogicalDDLMsgRecord, RmgrRecordInfoValid, RM_LOGICALDDLMSG_ID, XLOG_LOGICAL_DDL_MESSAGE, XLOG_LOGICAL_DDL_MESSAGE }, { DispatchGenericRecord, RmgrRecordInfoValid, RM_GENERIC_ID, XLOG_GENERIC_LOG, XLOG_GENERIC_LOG }, + { DispatchUBTree3Record, RmgrRecordInfoValid, RM_UBTREE3_ID, XLOG_UBTREE3_INSERT_PCR_INTERNAL, + XLOG_UBTREE3_INSERT_PCR_META }, + { DispatchUBTree4Record, RmgrRecordInfoValid, RM_UBTREE4_ID, XLOG_UBTREE4_UNLINK_PAGE, + XLOG_UBTREE4_MARK_PAGE_HALFDEAD }, }; /* Run from the dispatcher and txn worker thread. */ diff --git a/src/gausskernel/storage/access/ustore/knl_uextremeredo.cpp b/src/gausskernel/storage/access/ustore/knl_uextremeredo.cpp index 7891130679ba0fbea7815bf0ecd038ee4bdcb2b3..510c523a25a71fe8aaac3c6f6d84fe47b976707f 100644 --- a/src/gausskernel/storage/access/ustore/knl_uextremeredo.cpp +++ b/src/gausskernel/storage/access/ustore/knl_uextremeredo.cpp @@ -2357,6 +2357,84 @@ void RedoUndoActionBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdata } } +void RedoUbtree3UndoBlock(XLogBlockHead *blockhead, XLogBlockUndoParse *blockdatarec, + RedoBufferInfo *bufferinfo) +{ + uint8 info = XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK; + info &= XLOG_UBTREE_PCR_OP_MASK; + bool isInsert = true; + + switch (info) { + case XLOG_UBTREE3_DELETE_PCR: { + isInsert = false; + break; + } + case XLOG_UBTREE3_INSERT_PCR: + case XLOG_UBTREE3_DUP_INSERT: + case XLOG_UBTREE3_SPLIT_L: + case XLOG_UBTREE3_SPLIT_R: + case XLOG_UBTREE3_SPLIT_L_ROOT: + case XLOG_UBTREE3_SPLIT_R_ROOT: + break; + default: + ereport(PANIC, (errmsg("RedoUbtree3UndoBlock: unknown op code %u", info))); + } + + TransactionId recxid = blockdatarec->ubtree3UndoParse.recxid; + undo::XlogUndoMeta *xlundometa = &(blockdatarec->ubtree3UndoParse.xlundometa); + undo::XlogUndoMeta undometa; + CopyUndoMeta(*xlundometa, undometa); + XlUndoHeader *xlundohdr = &(blockdatarec->ubtree3UndoParse.xlundohdr); + XlUndoHeaderExtra *xlundohdrextra = &(blockdatarec->ubtree3UndoParse.xlundohdrextra); + UndoRecPtr urecptr = xlundohdr->urecptr; + bool skipInsert = undo::IsSkipInsertUndo(urecptr); + if (skipInsert) { + undometa.SetInfo(XLOG_UNDOMETA_INFO_SKIP); + } + + IndexTuple itup = (IndexTuple)(blockdatarec->maindata); + UndoRecord *undorec = t_thrd.ustore_cxt.undo_records[0]; + undorec->SetUrp(urecptr); + undorec->SetBlkprev(xlundohdrextra->blkprev); + undorec->SetOffset(blockdatarec->ubtree3UndoParse.offnum); + undorec->SetOldXactId(blockdatarec->ubtree3UndoParse.prevXidOfTuple); + + /* We need to pass in tablespace and relfilenode in PrepareUndo but we never explicitly + * wrote those information in the xlundohdr because we can grab them from the XLOG record itself. + */ + Oid relNode = blockdatarec->ubtree3UndoParse.relNode; + Oid spcNode = blockdatarec->ubtree3UndoParse.spcNode; + + if (isInsert) { + urecptr = UBTreePCRPrepareUndoInsert(xlundohdr->relOid, xlundohdrextra->partitionOid, + relNode, spcNode, UNDO_PERMANENT, recxid, InvalidCommandId, xlundohdrextra->blkprev, + xlundohdrextra->prevurp, blockdatarec->ubtree3UndoParse.blkno, xlundohdr, &undometa, + InvalidOffsetNumber, InvalidBuffer, false, blockdatarec->ubtree3UndoParse.uinfo, itup); + } else { + urecptr = UBTreePCRPrepareUndoDelete(xlundohdr->relOid, xlundohdrextra->partitionOid, + relNode, spcNode, UNDO_PERMANENT, InvalidBuffer, recxid, InvalidCommandId, xlundohdrextra->prevurp, + itup, blockdatarec->ubtree3UndoParse.blkno, xlundohdr, &undometa, + blockdatarec->ubtree3UndoParse.uinfo); + } + Assert(urecptr == xlundohdr->urecptr); + + if (!skipInsert) { + InsertPreparedUndo(t_thrd.ustore_cxt.urecvec, blockdatarec->ubtree3UndoParse.lsn); + } + UndoRecordVerify(undorec); + + XLogReaderState record; + XLogRecord decodedRecord; + decodedRecord.xl_xid = recxid; + record.decoded_record = &decodedRecord; + record.EndRecPtr = blockdatarec->ubtree3UndoParse.lsn; + + undo::RedoUndoMeta(&record, &undometa, xlundohdr->urecptr, t_thrd.ustore_cxt.urecvec->LastRecord(), + t_thrd.ustore_cxt.urecvec->LastRecordSize()); + + UHeapResetPreparedUndo(); +} + void RedoRollbackFinishBlock(XLogBlockHead *blockhead, XLogBlockUndoParse *blockdatarec, RedoBufferInfo *bufferinfo) { uint8 info = XLogBlockHeadGetInfo(blockhead) & ~XLR_INFO_MASK; diff --git a/src/include/access/rmgrlist.h b/src/include/access/rmgrlist.h index cb6c487dbef94b8b21f56657b72a4a4e98140b35..a829be3ca1eaaba612303eacfca25e07801f9efb 100644 --- a/src/include/access/rmgrlist.h +++ b/src/include/access/rmgrlist.h @@ -74,10 +74,6 @@ PG_RMGR(RM_UNDOACTION_ID, "UndoAction", undo::UndoXlogRollbackFinishRedo, undo:: PG_RMGR(RM_UBTREE_ID, "UBtree", UBTreeRedo, UBTreeDesc, UBTreeXlogStartup, UBTreeXlogCleanup, UBTreeSafeRestartPoint, NULL, NULL, ubtree_type_name) PG_RMGR(RM_UBTREE2_ID, "UBtree2", UBTree2Redo, UBTree2Desc, NULL, NULL, NULL, NULL, NULL, ubtree2_type_name) -PG_RMGR(RM_UBTREE3_ID, "UBtree3", UBTree3Redo, UBTree3Desc, NULL, NULL, NULL, UBTreePCRRollback, - NULL, ubtree3_type_name) -PG_RMGR(RM_UBTREE4_ID, "UBtree4", UBTree4Redo, UBTree4Desc, NULL, NULL, NULL, NULL, - NULL, ubtree4_type_name) PG_RMGR(RM_SEGPAGE_ID, "SegpageStorage", segpage_smgr_redo, segpage_smgr_desc, NULL, NULL, NULL, NULL, NULL, \ segpage_smgr_type_name) PG_RMGR(RM_REPLORIGIN_ID, "ReplicationOrigin", replorigin_redo, replorigin_desc, NULL, NULL, NULL, NULL, NULL, \ @@ -87,3 +83,7 @@ PG_RMGR(RM_COMPRESSION_REL_ID, "CompressionRelation", CfsShrinkRedo, CfsShrinkDe PG_RMGR(RM_LOGICALDDLMSG_ID, "LogicalDDLMessage", logicalddlmsg_redo, logicalddlmsg_desc, NULL, NULL, NULL, NULL, NULL, \ logicalddlmsg_type_name) PG_RMGR(RM_GENERIC_ID, "Generic", generic_redo, generic_desc, NULL, NULL, NULL, NULL, NULL, NULL) +PG_RMGR(RM_UBTREE3_ID, "UBtree3", UBTree3Redo, UBTree3Desc, NULL, NULL, NULL, UBTreePCRRollback, + NULL, ubtree3_type_name) +PG_RMGR(RM_UBTREE4_ID, "UBtree4", UBTree4Redo, UBTree4Desc, NULL, NULL, NULL, NULL, \ + NULL, ubtree4_type_name) diff --git a/src/include/access/ustore/knl_uextremeredo.h b/src/include/access/ustore/knl_uextremeredo.h index af754caa017dc08613ff82d34e572a3b7a3a5a15..d2a8f87bd31cbcc4fc480345baa2112abb498847 100644 --- a/src/include/access/ustore/knl_uextremeredo.h +++ b/src/include/access/ustore/knl_uextremeredo.h @@ -50,4 +50,5 @@ void RedoUHeapUndoBlock(XLogBlockHead *blockhead, XLogBlockUndoParse *blockdatar void RedoUndoBlock(XLogBlockHead *blockhead, XLogBlockUndoParse *blockdatarec, RedoBufferInfo *bufferinfo); void RedoUndoActionBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo); void RedoRollbackFinishBlock(XLogBlockHead *blockhead, XLogBlockUndoParse *blockdatarec, RedoBufferInfo *bufferinfo); +void RedoUbtree3UndoBlock(XLogBlockHead *blockhead, XLogBlockUndoParse *blockdatarec, RedoBufferInfo *bufferinfo); #endif diff --git a/src/include/access/xlogproc.h b/src/include/access/xlogproc.h index eab504179b346c240c8551bea49a08b248f89970..01fcddf49a1d1ec7ff4ab29f3b737a39d7b9c132 100755 --- a/src/include/access/xlogproc.h +++ b/src/include/access/xlogproc.h @@ -346,6 +346,20 @@ struct multiInsertUndoParse { undo::XlogUndoMeta xlundometa; }; +struct ubtree3UndoParse { + TransactionId recxid; + TransactionId prevXidOfTuple; + BlockNumber blkno; + Oid spcNode; + Oid relNode; + XLogRecPtr lsn; + OffsetNumber offnum; + UBTreeUndoInfo uinfo; + XlUndoHeader xlundohdr; + XlUndoHeaderExtra xlundohdrextra; + undo::XlogUndoMeta xlundometa; +}; + struct rollbackFinishParse { UndoSlotPtr slotPtr; XLogRecPtr lsn; @@ -391,6 +405,7 @@ typedef struct { struct undoCleanParse undoCleanParse; struct rollbackFinishParse rollbackFinishParse; struct multiInsertUndoParse multiInsertUndoParse; + struct ubtree3UndoParse ubtree3UndoParse; }; } XLogBlockUndoParse; /* ********BLOCK Undo END ***************** */ @@ -1169,6 +1184,11 @@ void Btree2RedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdata extern void UBTreeRedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdatarec, RedoBufferInfo* bufferinfo); extern void UBTree2RedoDataBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, RedoBufferInfo *bufferinfo); +extern void UBTree3RedoDataBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, + RedoBufferInfo *bufferinfo); +extern void UBTree4RedoDataBlock(XLogBlockHead *blockhead, XLogBlockDataParse *blockdatarec, + RedoBufferInfo *bufferinfo); +extern void XLogRecSetUBtree3UndoBlockState(XLogReaderState *record, uint32 blockid, XLogRecParseState *undostate); extern void HashRedoDataBlock(XLogBlockHead* blockhead, XLogBlockDataParse* blockdatarec, RedoBufferInfo* bufferinfo); XLogRecParseState* XactXlogCsnlogParseToBlock(XLogReaderState* record, uint32* blocknum, TransactionId xid, int nsubxids, TransactionId* subxids, CommitSeqNo csn, XLogRecParseState* recordstatehead); @@ -1207,6 +1227,8 @@ extern XLogRecParseState* BtreeRedoParseToBlock(XLogReaderState* record, uint32* /* UBTree */ extern XLogRecParseState* UBTreeRedoParseToBlock(XLogReaderState* record, uint32* blocknum); extern XLogRecParseState* UBTree2RedoParseToBlock(XLogReaderState* record, uint32* blocknum); +extern XLogRecParseState* UBTree3RedoParseToBlock(XLogReaderState* record, uint32* blocknum); +extern XLogRecParseState* UBTree4RedoParseToBlock(XLogReaderState* record, uint32* blocknum); extern XLogRecParseState* Heap3RedoParseToBlock(XLogReaderState* record, uint32* blocknum);