⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gistxlog.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * gistxlog.c *	  WAL replay logic for GiST. * * * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION *			 $PostgreSQL: pgsql/src/backend/access/gist/gistxlog.c,v 1.9 2005/09/22 20:44:36 momjian Exp $ *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/gist_private.h"#include "access/gistscan.h"#include "access/heapam.h"#include "catalog/index.h"#include "commands/vacuum.h"#include "miscadmin.h"#include "utils/memutils.h"typedef struct{	gistxlogEntryUpdate *data;	int			len;	IndexTuple *itup;	OffsetNumber *todelete;} EntryUpdateRecord;typedef struct{	gistxlogPage *header;	IndexTuple *itup;} NewPage;typedef struct{	gistxlogPageSplit *data;	NewPage    *page;} PageSplitRecord;/* track for incomplete inserts, idea was taken from nbtxlog.c */typedef struct gistIncompleteInsert{	RelFileNode node;	BlockNumber origblkno;		/* for splits */	ItemPointerData key;	int			lenblk;	BlockNumber *blkno;	XLogRecPtr	lsn;	BlockNumber *path;	int			pathlen;} gistIncompleteInsert;MemoryContext opCtx;MemoryContext insertCtx;static List *incomplete_inserts;#define ItemPointerEQ( a, b )	\	( \	ItemPointerGetOffsetNumber(a) == ItemPointerGetOffsetNumber(b) && \	ItemPointerGetBlockNumber (a) == ItemPointerGetBlockNumber(b) \		)static voidpushIncompleteInsert(RelFileNode node, XLogRecPtr lsn, ItemPointerData key,					 BlockNumber *blkno, int lenblk,					 PageSplitRecord *xlinfo /* to extract blkno info */ ){	MemoryContext oldCxt = MemoryContextSwitchTo(insertCtx);	gistIncompleteInsert *ninsert = (gistIncompleteInsert *) palloc(sizeof(gistIncompleteInsert));	ninsert->node = node;	ninsert->key = key;	ninsert->lsn = lsn;	if (lenblk && blkno)	{		ninsert->lenblk = lenblk;		ninsert->blkno = (BlockNumber *) palloc(sizeof(BlockNumber) * ninsert->lenblk);		memcpy(ninsert->blkno, blkno, sizeof(BlockNumber) * ninsert->lenblk);		ninsert->origblkno = *blkno;	}	else	{		int			i;		Assert(xlinfo);		ninsert->lenblk = xlinfo->data->npage;		ninsert->blkno = (BlockNumber *) palloc(sizeof(BlockNumber) * ninsert->lenblk);		for (i = 0; i < ninsert->lenblk; i++)			ninsert->blkno[i] = xlinfo->page[i].header->blkno;		ninsert->origblkno = xlinfo->data->origblkno;	}	Assert(ninsert->lenblk > 0);	incomplete_inserts = lappend(incomplete_inserts, ninsert);	MemoryContextSwitchTo(oldCxt);}static voidforgetIncompleteInsert(RelFileNode node, ItemPointerData key){	ListCell   *l;	foreach(l, incomplete_inserts)	{		gistIncompleteInsert *insert = (gistIncompleteInsert *) lfirst(l);		if (RelFileNodeEquals(node, insert->node) && ItemPointerEQ(&(insert->key), &(key)))		{			/* found */			pfree(insert->blkno);			incomplete_inserts = list_delete_ptr(incomplete_inserts, insert);			pfree(insert);			break;		}	}}static voiddecodeEntryUpdateRecord(EntryUpdateRecord *decoded, XLogRecord *record){	char	   *begin = XLogRecGetData(record),			   *ptr;	int			i = 0,				addpath = 0;	decoded->data = (gistxlogEntryUpdate *) begin;	if (decoded->data->ntodelete)	{		decoded->todelete = (OffsetNumber *) (begin + sizeof(gistxlogEntryUpdate) + addpath);		addpath = MAXALIGN(sizeof(OffsetNumber) * decoded->data->ntodelete);	}	else		decoded->todelete = NULL;	decoded->len = 0;	ptr = begin + sizeof(gistxlogEntryUpdate) + addpath;	while (ptr - begin < record->xl_len)	{		decoded->len++;		ptr += IndexTupleSize((IndexTuple) ptr);	}	decoded->itup = (IndexTuple *) palloc(sizeof(IndexTuple) * decoded->len);	ptr = begin + sizeof(gistxlogEntryUpdate) + addpath;	while (ptr - begin < record->xl_len)	{		decoded->itup[i] = (IndexTuple) ptr;		ptr += IndexTupleSize(decoded->itup[i]);		i++;	}}/* * redo any page update (except page split) */static voidgistRedoEntryUpdateRecord(XLogRecPtr lsn, XLogRecord *record, bool isnewroot){	EntryUpdateRecord xlrec;	Relation	reln;	Buffer		buffer;	Page		page;	decodeEntryUpdateRecord(&xlrec, record);	reln = XLogOpenRelation(xlrec.data->node);	if (!RelationIsValid(reln))		return;	buffer = XLogReadBuffer(false, reln, xlrec.data->blkno);	if (!BufferIsValid(buffer))		elog(PANIC, "block %u unfound", xlrec.data->blkno);	page = (Page) BufferGetPage(buffer);	if (isnewroot)	{		if (!PageIsNew((PageHeader) page) && XLByteLE(lsn, PageGetLSN(page)))		{			LockBuffer(buffer, BUFFER_LOCK_UNLOCK);			ReleaseBuffer(buffer);			return;		}	}	else	{		if (PageIsNew((PageHeader) page))			elog(PANIC, "uninitialized page %u", xlrec.data->blkno);		if (XLByteLE(lsn, PageGetLSN(page)))		{			LockBuffer(buffer, BUFFER_LOCK_UNLOCK);			ReleaseBuffer(buffer);			return;		}	}	if (xlrec.data->isemptypage)	{		while (!PageIsEmpty(page))			PageIndexTupleDelete(page, FirstOffsetNumber);		if (xlrec.data->blkno == GIST_ROOT_BLKNO)			GistPageSetLeaf(page);		else			GistPageSetDeleted(page);	}	else	{		if (isnewroot)			GISTInitBuffer(buffer, 0);		else if (xlrec.data->ntodelete)		{			int			i;			for (i = 0; i < xlrec.data->ntodelete; i++)				PageIndexTupleDelete(page, xlrec.todelete[i]);			if (GistPageIsLeaf(page))				GistMarkTuplesDeleted(page);		}		/* add tuples */		if (xlrec.len > 0)			gistfillbuffer(reln, page, xlrec.itup, xlrec.len, InvalidOffsetNumber);		/*		 * special case: leafpage, nothing to insert, nothing to delete, then		 * vacuum marks page		 */		if (GistPageIsLeaf(page) && xlrec.len == 0 && xlrec.data->ntodelete == 0)			GistClearTuplesDeleted(page);	}	PageSetLSN(page, lsn);	PageSetTLI(page, ThisTimeLineID);	GistPageGetOpaque(page)->rightlink = InvalidBlockNumber;	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);	WriteBuffer(buffer);	if (ItemPointerIsValid(&(xlrec.data->key)))	{		if (incomplete_inserts != NIL)			forgetIncompleteInsert(xlrec.data->node, xlrec.data->key);		if (!isnewroot && xlrec.data->blkno != GIST_ROOT_BLKNO)			pushIncompleteInsert(xlrec.data->node, lsn, xlrec.data->key,								 &(xlrec.data->blkno), 1,								 NULL);	}}static voiddecodePageSplitRecord(PageSplitRecord *decoded, XLogRecord *record){	char	   *begin = XLogRecGetData(record),			   *ptr;	int			j,				i = 0;	decoded->data = (gistxlogPageSplit *) begin;	decoded->page = (NewPage *) palloc(sizeof(NewPage) * decoded->data->npage);	ptr = begin + sizeof(gistxlogPageSplit);	for (i = 0; i < decoded->data->npage; i++)	{		Assert(ptr - begin < record->xl_len);		decoded->page[i].header = (gistxlogPage *) ptr;		ptr += sizeof(gistxlogPage);		decoded->page[i].itup = (IndexTuple *)			palloc(sizeof(IndexTuple) * decoded->page[i].header->num);		j = 0;		while (j < decoded->page[i].header->num)		{			Assert(ptr - begin < record->xl_len);			decoded->page[i].itup[j] = (IndexTuple) ptr;			ptr += IndexTupleSize((IndexTuple) ptr);			j++;		}	}}static voidgistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record){	PageSplitRecord xlrec;	Relation	reln;	Buffer		buffer;	Page		page;	int			i;	int			flags = 0;	decodePageSplitRecord(&xlrec, record);	reln = XLogOpenRelation(xlrec.data->node);	if (!RelationIsValid(reln))		return;	/* first of all wee need get F_LEAF flag from original page */	buffer = XLogReadBuffer(false, reln, xlrec.data->origblkno);	if (!BufferIsValid(buffer))		elog(PANIC, "block %u unfound", xlrec.data->origblkno);	page = (Page) BufferGetPage(buffer);	if (PageIsNew((PageHeader) page))		elog(PANIC, "uninitialized page %u", xlrec.data->origblkno);	flags = (GistPageIsLeaf(page)) ? F_LEAF : 0;	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);	ReleaseBuffer(buffer);	/* loop around all pages */	for (i = 0; i < xlrec.data->npage; i++)	{		NewPage    *newpage = xlrec.page + i;		bool		isorigpage = (xlrec.data->origblkno == newpage->header->blkno) ? true : false;		buffer = XLogReadBuffer(!isorigpage, reln, newpage->header->blkno);		if (!BufferIsValid(buffer))			elog(PANIC, "block %u unfound", newpage->header->blkno);		page = (Page) BufferGetPage(buffer);		if (XLByteLE(lsn, PageGetLSN(page)))		{			LockBuffer(buffer, BUFFER_LOCK_UNLOCK);			ReleaseBuffer(buffer);			continue;		}		/* ok, clear buffer */		GISTInitBuffer(buffer, flags);		/* and fill it */		gistfillbuffer(reln, page, newpage->itup, newpage->header->num, FirstOffsetNumber);		PageSetLSN(page, lsn);		PageSetTLI(page, ThisTimeLineID);		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);		WriteBuffer(buffer);	}	if (ItemPointerIsValid(&(xlrec.data->key)))	{		if (incomplete_inserts != NIL)			forgetIncompleteInsert(xlrec.data->node, xlrec.data->key);		pushIncompleteInsert(xlrec.data->node, lsn, xlrec.data->key,							 NULL, 0,							 &xlrec);	}}static voidgistRedoCreateIndex(XLogRecPtr lsn, XLogRecord *record){	RelFileNode *node = (RelFileNode *) XLogRecGetData(record);	Relation	reln;	Buffer		buffer;	Page		page;	reln = XLogOpenRelation(*node);	if (!RelationIsValid(reln))		return;	buffer = XLogReadBuffer(true, reln, GIST_ROOT_BLKNO);	if (!BufferIsValid(buffer))		elog(PANIC, "root block unfound");	page = (Page) BufferGetPage(buffer);	if (!PageIsNew((PageHeader) page) && XLByteLE(lsn, PageGetLSN(page)))	{		LockBuffer(buffer, BUFFER_LOCK_UNLOCK);		ReleaseBuffer(buffer);		return;	}	GISTInitBuffer(buffer, F_LEAF);	PageSetLSN(page, lsn);	PageSetTLI(page, ThisTimeLineID);	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);	WriteBuffer(buffer);}static voidgistRedoCompleteInsert(XLogRecPtr lsn, XLogRecord *record){	char	   *begin = XLogRecGetData(record),			   *ptr;	gistxlogInsertComplete *xlrec;	xlrec = (gistxlogInsertComplete *) begin;	ptr = begin + sizeof(gistxlogInsertComplete);	while (ptr - begin < record->xl_len)	{		Assert(record->xl_len - (ptr - begin) >= sizeof(ItemPointerData));		forgetIncompleteInsert(xlrec->node, *((ItemPointerData *) ptr));		ptr += sizeof(ItemPointerData);	}}voidgist_redo(XLogRecPtr lsn, XLogRecord *record){	uint8		info = record->xl_info & ~XLR_INFO_MASK;	MemoryContext oldCxt;	oldCxt = MemoryContextSwitchTo(opCtx);	switch (info)	{		case XLOG_GIST_ENTRY_UPDATE:		case XLOG_GIST_ENTRY_DELETE:			gistRedoEntryUpdateRecord(lsn, record, false);			break;		case XLOG_GIST_NEW_ROOT:			gistRedoEntryUpdateRecord(lsn, record, true);			break;		case XLOG_GIST_PAGE_SPLIT:			gistRedoPageSplitRecord(lsn, record);			break;		case XLOG_GIST_CREATE_INDEX:			gistRedoCreateIndex(lsn, record);			break;		case XLOG_GIST_INSERT_COMPLETE:			gistRedoCompleteInsert(lsn, record);			break;		default:			elog(PANIC, "gist_redo: unknown op code %u", info);	}	MemoryContextSwitchTo(oldCxt);	MemoryContextReset(opCtx);}static voidout_target(char *buf, RelFileNode node, ItemPointerData key){	sprintf(buf + strlen(buf), "rel %u/%u/%u; tid %u/%u",			node.spcNode, node.dbNode, node.relNode,			ItemPointerGetBlockNumber(&key),			ItemPointerGetOffsetNumber(&key));}static voidout_gistxlogEntryUpdate(char *buf, gistxlogEntryUpdate *xlrec){	out_target(buf, xlrec->node, xlrec->key);	sprintf(buf + strlen(buf), "; block number %u",			xlrec->blkno);}static voidout_gistxlogPageSplit(char *buf, gistxlogPageSplit *xlrec){	strcat(buf, "page_split: ");	out_target(buf, xlrec->node, xlrec->key);	sprintf(buf + strlen(buf), "; block number %u splits to %d pages",			xlrec->origblkno, xlrec->npage);}voidgist_desc(char *buf, uint8 xl_info, char *rec){	uint8		info = xl_info & ~XLR_INFO_MASK;	switch (info)	{		case XLOG_GIST_ENTRY_UPDATE:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -