📄 ginxlog.c
字号:
PageSetTLI(lpage, ThisTimeLineID); MarkBufferDirty(lbuffer); if (!data->isLeaf && data->updateBlkno != InvalidBlockNumber) forgetIncompleteSplit(data->node, data->leftChildBlkno, data->updateBlkno); if (data->isRootSplit) { Buffer rootBuf = XLogReadBuffer(reln, data->rootBlkno, false); Page rootPage = BufferGetPage(rootBuf); GinInitBuffer(rootBuf, flags & ~GIN_LEAF); if (data->isData) { Assert(data->rootBlkno != GIN_ROOT_BLKNO); dataFillRoot(NULL, rootBuf, lbuffer, rbuffer); } else { Assert(data->rootBlkno == GIN_ROOT_BLKNO); entryFillRoot(NULL, rootBuf, lbuffer, rbuffer); } PageSetLSN(rootPage, lsn); PageSetTLI(rootPage, ThisTimeLineID); MarkBufferDirty(rootBuf); UnlockReleaseBuffer(rootBuf); } else pushIncompleteSplit(data->node, data->lblkno, data->rblkno, data->rootBlkno); UnlockReleaseBuffer(rbuffer); UnlockReleaseBuffer(lbuffer);}static voidginRedoVacuumPage(XLogRecPtr lsn, XLogRecord *record){ ginxlogVacuumPage *data = (ginxlogVacuumPage *) XLogRecGetData(record); Relation reln; Buffer buffer; Page page; /* nothing else to do if page was backed up (and no info to do it with) */ if (record->xl_info & XLR_BKP_BLOCK_1) return; reln = XLogOpenRelation(data->node); buffer = XLogReadBuffer(reln, data->blkno, false); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); if (GinPageIsData(page)) { memcpy(GinDataPageGetData(page), XLogRecGetData(record) + sizeof(ginxlogVacuumPage), GinSizeOfItem(page) *data->nitem); GinPageGetOpaque(page)->maxoff = data->nitem; } else { OffsetNumber i, *tod; IndexTuple itup = (IndexTuple) (XLogRecGetData(record) + sizeof(ginxlogVacuumPage)); tod = (OffsetNumber *) palloc(sizeof(OffsetNumber) * PageGetMaxOffsetNumber(page)); for (i = FirstOffsetNumber; i <= PageGetMaxOffsetNumber(page); i++) tod[i - 1] = i; PageIndexMultiDelete(page, tod, PageGetMaxOffsetNumber(page)); for (i = 0; i < data->nitem; i++) { if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), InvalidOffsetNumber, false, false) == InvalidOffsetNumber) elog(ERROR, "failed to add item to index page in %u/%u/%u", data->node.spcNode, data->node.dbNode, data->node.relNode); itup = (IndexTuple) (((char *) itup) + MAXALIGN(IndexTupleSize(itup))); } } PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer);}static voidginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record){ ginxlogDeletePage *data = (ginxlogDeletePage *) XLogRecGetData(record); Relation reln; Buffer buffer; Page page; reln = XLogOpenRelation(data->node); if (!(record->xl_info & XLR_BKP_BLOCK_1)) { buffer = XLogReadBuffer(reln, data->blkno, false); page = BufferGetPage(buffer); Assert(GinPageIsData(page)); GinPageGetOpaque(page)->flags = GIN_DELETED; PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer); } if (!(record->xl_info & XLR_BKP_BLOCK_2)) { buffer = XLogReadBuffer(reln, data->parentBlkno, false); page = BufferGetPage(buffer); Assert(GinPageIsData(page)); Assert(!GinPageIsLeaf(page)); PageDeletePostingItem(page, data->parentOffset); PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer); } if (!(record->xl_info & XLR_BKP_BLOCK_3) && data->leftBlkno != InvalidBlockNumber) { buffer = XLogReadBuffer(reln, data->leftBlkno, false); page = BufferGetPage(buffer); Assert(GinPageIsData(page)); GinPageGetOpaque(page)->rightlink = data->rightLink; PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer); }}voidgin_redo(XLogRecPtr lsn, XLogRecord *record){ uint8 info = record->xl_info & ~XLR_INFO_MASK; topCtx = MemoryContextSwitchTo(opCtx); switch (info) { case XLOG_GIN_CREATE_INDEX: ginRedoCreateIndex(lsn, record); break; case XLOG_GIN_CREATE_PTREE: ginRedoCreatePTree(lsn, record); break; case XLOG_GIN_INSERT: ginRedoInsert(lsn, record); break; case XLOG_GIN_SPLIT: ginRedoSplit(lsn, record); break; case XLOG_GIN_VACUUM_PAGE: ginRedoVacuumPage(lsn, record); break; case XLOG_GIN_DELETE_PAGE: ginRedoDeletePage(lsn, record); break; default: elog(PANIC, "gin_redo: unknown op code %u", info); } MemoryContextSwitchTo(topCtx); MemoryContextReset(opCtx);}static voiddesc_node(StringInfo buf, RelFileNode node, BlockNumber blkno){ appendStringInfo(buf, "node: %u/%u/%u blkno: %u", node.spcNode, node.dbNode, node.relNode, blkno);}voidgin_desc(StringInfo buf, uint8 xl_info, char *rec){ uint8 info = xl_info & ~XLR_INFO_MASK; switch (info) { case XLOG_GIN_CREATE_INDEX: appendStringInfo(buf, "Create index, "); desc_node(buf, *(RelFileNode *) rec, GIN_ROOT_BLKNO); break; case XLOG_GIN_CREATE_PTREE: appendStringInfo(buf, "Create posting tree, "); desc_node(buf, ((ginxlogCreatePostingTree *) rec)->node, ((ginxlogCreatePostingTree *) rec)->blkno); break; case XLOG_GIN_INSERT: appendStringInfo(buf, "Insert item, "); desc_node(buf, ((ginxlogInsert *) rec)->node, ((ginxlogInsert *) rec)->blkno); appendStringInfo(buf, " offset: %u nitem: %u isdata: %c isleaf %c isdelete %c updateBlkno:%u", ((ginxlogInsert *) rec)->offset, ((ginxlogInsert *) rec)->nitem, (((ginxlogInsert *) rec)->isData) ? 'T' : 'F', (((ginxlogInsert *) rec)->isLeaf) ? 'T' : 'F', (((ginxlogInsert *) rec)->isDelete) ? 'T' : 'F', ((ginxlogInsert *) rec)->updateBlkno ); break; case XLOG_GIN_SPLIT: appendStringInfo(buf, "Page split, "); desc_node(buf, ((ginxlogSplit *) rec)->node, ((ginxlogSplit *) rec)->lblkno); appendStringInfo(buf, " isrootsplit: %c", (((ginxlogSplit *) rec)->isRootSplit) ? 'T' : 'F'); break; case XLOG_GIN_VACUUM_PAGE: appendStringInfo(buf, "Vacuum page, "); desc_node(buf, ((ginxlogVacuumPage *) rec)->node, ((ginxlogVacuumPage *) rec)->blkno); break; case XLOG_GIN_DELETE_PAGE: appendStringInfo(buf, "Delete page, "); desc_node(buf, ((ginxlogDeletePage *) rec)->node, ((ginxlogDeletePage *) rec)->blkno); break; default: elog(PANIC, "gin_desc: unknown op code %u", info); }}voidgin_xlog_startup(void){ incomplete_splits = NIL; opCtx = AllocSetContextCreate(CurrentMemoryContext, "GIN recovery temporary context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE);}static voidginContinueSplit(ginIncompleteSplit *split){ GinBtreeData btree; Relation reln; Buffer buffer; GinBtreeStack stack; /* * elog(NOTICE,"ginContinueSplit root:%u l:%u r:%u", split->rootBlkno, * split->leftBlkno, split->rightBlkno); */ reln = XLogOpenRelation(split->node); buffer = XLogReadBuffer(reln, split->leftBlkno, false); if (split->rootBlkno == GIN_ROOT_BLKNO) { prepareEntryScan(&btree, reln, (Datum) 0, NULL); btree.entry = ginPageGetLinkItup(buffer); } else { Page page = BufferGetPage(buffer); prepareDataScan(&btree, reln); PostingItemSetBlockNumber(&(btree.pitem), split->leftBlkno); if (GinPageIsLeaf(page)) btree.pitem.key = *(ItemPointerData *) GinDataPageGetItem(page, GinPageGetOpaque(page)->maxoff); else btree.pitem.key = ((PostingItem *) GinDataPageGetItem(page, GinPageGetOpaque(page)->maxoff))->key; } btree.rightblkno = split->rightBlkno; stack.blkno = split->leftBlkno; stack.buffer = buffer; stack.off = InvalidOffsetNumber; stack.parent = NULL; findParents(&btree, &stack, split->rootBlkno); ginInsertValue(&btree, stack.parent); UnlockReleaseBuffer(buffer);}voidgin_xlog_cleanup(void){ ListCell *l; MemoryContext topCtx; topCtx = MemoryContextSwitchTo(opCtx); foreach(l, incomplete_splits) { ginIncompleteSplit *split = (ginIncompleteSplit *) lfirst(l); ginContinueSplit(split); MemoryContextReset(opCtx); } MemoryContextSwitchTo(topCtx); MemoryContextDelete(opCtx); incomplete_splits = NIL;}boolgin_safe_restartpoint(void){ if (incomplete_splits) return false; return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -