📄 ginxlog.c
字号:
/*------------------------------------------------------------------------- * * ginxlog.c * WAL replay logic for inverted index. * * * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION * $PostgreSQL: pgsql/src/backend/access/gin/ginxlog.c,v 1.12 2008/01/01 19:45:46 momjian Exp $ *------------------------------------------------------------------------- */#include "postgres.h"#include "access/gin.h"#include "access/heapam.h"#include "utils/memutils.h"static MemoryContext opCtx; /* working memory for operations */static MemoryContext topCtx;typedef struct ginIncompleteSplit{ RelFileNode node; BlockNumber leftBlkno; BlockNumber rightBlkno; BlockNumber rootBlkno;} ginIncompleteSplit;static List *incomplete_splits;static voidpushIncompleteSplit(RelFileNode node, BlockNumber leftBlkno, BlockNumber rightBlkno, BlockNumber rootBlkno){ ginIncompleteSplit *split; MemoryContextSwitchTo(topCtx); split = palloc(sizeof(ginIncompleteSplit)); split->node = node; split->leftBlkno = leftBlkno; split->rightBlkno = rightBlkno; split->rootBlkno = rootBlkno; incomplete_splits = lappend(incomplete_splits, split); MemoryContextSwitchTo(opCtx);}static voidforgetIncompleteSplit(RelFileNode node, BlockNumber leftBlkno, BlockNumber updateBlkno){ ListCell *l; foreach(l, incomplete_splits) { ginIncompleteSplit *split = (ginIncompleteSplit *) lfirst(l); if (RelFileNodeEquals(node, split->node) && leftBlkno == split->leftBlkno && updateBlkno == split->rightBlkno) { incomplete_splits = list_delete_ptr(incomplete_splits, split); break; } }}static voidginRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record){ RelFileNode *node = (RelFileNode *) XLogRecGetData(record); Relation reln; Buffer buffer; Page page; reln = XLogOpenRelation(*node); buffer = XLogReadBuffer(reln, GIN_ROOT_BLKNO, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); GinInitBuffer(buffer, GIN_LEAF); PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer);}static voidginRedoCreatePTree(XLogRecPtr lsn, XLogRecord *record){ ginxlogCreatePostingTree *data = (ginxlogCreatePostingTree *) XLogRecGetData(record); ItemPointerData *items = (ItemPointerData *) (XLogRecGetData(record) + sizeof(ginxlogCreatePostingTree)); Relation reln; Buffer buffer; Page page; reln = XLogOpenRelation(data->node); buffer = XLogReadBuffer(reln, data->blkno, true); Assert(BufferIsValid(buffer)); page = (Page) BufferGetPage(buffer); GinInitBuffer(buffer, GIN_DATA | GIN_LEAF); memcpy(GinDataPageGetData(page), items, sizeof(ItemPointerData) * data->nitem); GinPageGetOpaque(page)->maxoff = data->nitem; PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); UnlockReleaseBuffer(buffer);}static voidginRedoInsert(XLogRecPtr lsn, XLogRecord *record){ ginxlogInsert *data = (ginxlogInsert *) XLogRecGetData(record); Relation reln; Buffer buffer; Page page; /* nothing else to do if page was backed up */ 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 (data->isData) { Assert(data->isDelete == FALSE); Assert(GinPageIsData(page)); if (!XLByteLE(lsn, PageGetLSN(page))) { if (data->isLeaf) { OffsetNumber i; ItemPointerData *items = (ItemPointerData *) (XLogRecGetData(record) + sizeof(ginxlogInsert)); Assert(GinPageIsLeaf(page)); Assert(data->updateBlkno == InvalidBlockNumber); for (i = 0; i < data->nitem; i++) GinDataPageAddItem(page, items + i, data->offset + i); } else { PostingItem *pitem; Assert(!GinPageIsLeaf(page)); if (data->updateBlkno != InvalidBlockNumber) { /* update link to right page after split */ pitem = (PostingItem *) GinDataPageGetItem(page, data->offset); PostingItemSetBlockNumber(pitem, data->updateBlkno); } pitem = (PostingItem *) (XLogRecGetData(record) + sizeof(ginxlogInsert)); GinDataPageAddItem(page, pitem, data->offset); } } if (!data->isLeaf && data->updateBlkno != InvalidBlockNumber) { PostingItem *pitem = (PostingItem *) (XLogRecGetData(record) + sizeof(ginxlogInsert)); forgetIncompleteSplit(data->node, PostingItemGetBlockNumber(pitem), data->updateBlkno); } } else { IndexTuple itup; Assert(!GinPageIsData(page)); if (!XLByteLE(lsn, PageGetLSN(page))) { if (data->updateBlkno != InvalidBlockNumber) { /* update link to right page after split */ Assert(!GinPageIsLeaf(page)); Assert(data->offset >= FirstOffsetNumber && data->offset <= PageGetMaxOffsetNumber(page)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, data->offset)); ItemPointerSet(&itup->t_tid, data->updateBlkno, InvalidOffsetNumber); } if (data->isDelete) { Assert(GinPageIsLeaf(page)); Assert(data->offset >= FirstOffsetNumber && data->offset <= PageGetMaxOffsetNumber(page)); PageIndexTupleDelete(page, data->offset); } itup = (IndexTuple) (XLogRecGetData(record) + sizeof(ginxlogInsert)); if (PageAddItem(page, (Item) itup, IndexTupleSize(itup), data->offset, 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); } if (!data->isLeaf && data->updateBlkno != InvalidBlockNumber) { itup = (IndexTuple) (XLogRecGetData(record) + sizeof(ginxlogInsert)); forgetIncompleteSplit(data->node, GinItemPointerGetBlockNumber(&itup->t_tid), data->updateBlkno); } } if (!XLByteLE(lsn, PageGetLSN(page))) { PageSetLSN(page, lsn); PageSetTLI(page, ThisTimeLineID); MarkBufferDirty(buffer); } UnlockReleaseBuffer(buffer);}static voidginRedoSplit(XLogRecPtr lsn, XLogRecord *record){ ginxlogSplit *data = (ginxlogSplit *) XLogRecGetData(record); Relation reln; Buffer lbuffer, rbuffer; Page lpage, rpage; uint32 flags = 0; reln = XLogOpenRelation(data->node); if (data->isLeaf) flags |= GIN_LEAF; if (data->isData) flags |= GIN_DATA; lbuffer = XLogReadBuffer(reln, data->lblkno, data->isRootSplit); Assert(BufferIsValid(lbuffer)); lpage = (Page) BufferGetPage(lbuffer); GinInitBuffer(lbuffer, flags); rbuffer = XLogReadBuffer(reln, data->rblkno, true); Assert(BufferIsValid(rbuffer)); rpage = (Page) BufferGetPage(rbuffer); GinInitBuffer(rbuffer, flags); GinPageGetOpaque(lpage)->rightlink = BufferGetBlockNumber(rbuffer); GinPageGetOpaque(rpage)->rightlink = data->rrlink; if (data->isData) { char *ptr = XLogRecGetData(record) + sizeof(ginxlogSplit); Size sizeofitem = GinSizeOfItem(lpage); OffsetNumber i; ItemPointer bound; for (i = 0; i < data->separator; i++) { GinDataPageAddItem(lpage, ptr, InvalidOffsetNumber); ptr += sizeofitem; } for (i = data->separator; i < data->nitem; i++) { GinDataPageAddItem(rpage, ptr, InvalidOffsetNumber); ptr += sizeofitem; } /* set up right key */ bound = GinDataPageGetRightBound(lpage); if (data->isLeaf) *bound = *(ItemPointerData *) GinDataPageGetItem(lpage, GinPageGetOpaque(lpage)->maxoff); else *bound = ((PostingItem *) GinDataPageGetItem(lpage, GinPageGetOpaque(lpage)->maxoff))->key; bound = GinDataPageGetRightBound(rpage); *bound = data->rightbound; } else { IndexTuple itup = (IndexTuple) (XLogRecGetData(record) + sizeof(ginxlogSplit)); OffsetNumber i; for (i = 0; i < data->separator; i++) { if (PageAddItem(lpage, (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))); } for (i = data->separator; i < data->nitem; i++) { if (PageAddItem(rpage, (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(rpage, lsn); PageSetTLI(rpage, ThisTimeLineID); MarkBufferDirty(rbuffer); PageSetLSN(lpage, lsn);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -