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

📄 gistvacuum.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * gistvacuum.c *	  interface routines for the postgres GiST index access method. * * * 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/gist/gistvacuum.c,v 1.34 2008/01/01 19:45:46 momjian Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/genam.h"#include "access/gist_private.h"#include "access/heapam.h"#include "commands/vacuum.h"#include "miscadmin.h"#include "storage/freespace.h"#include "utils/memutils.h"typedef struct GistBulkDeleteResult{	IndexBulkDeleteResult std;	/* common state */	bool		needFullVacuum;} GistBulkDeleteResult;typedef struct{	GISTSTATE	giststate;	Relation	index;	MemoryContext opCtx;	GistBulkDeleteResult *result;	BufferAccessStrategy strategy;} GistVacuum;typedef struct{	IndexTuple *itup;	int			ituplen;	bool		emptypage;} ArrayTuple;/* * Make union of keys on page */static IndexTuplePageMakeUnionKey(GistVacuum *gv, Buffer buffer){	Page		page = BufferGetPage(buffer);	IndexTuple *vec,				tmp,				res;	int			veclen = 0;	MemoryContext oldCtx = MemoryContextSwitchTo(gv->opCtx);	vec = gistextractpage(page, &veclen);	/*	 * we call gistunion() in temprorary context because user-defined	 * functions called in gistunion() may do not free all memory	 */	tmp = gistunion(gv->index, vec, veclen, &(gv->giststate));	MemoryContextSwitchTo(oldCtx);	res = (IndexTuple) palloc(IndexTupleSize(tmp));	memcpy(res, tmp, IndexTupleSize(tmp));	ItemPointerSetBlockNumber(&(res->t_tid), BufferGetBlockNumber(buffer));	GistTupleSetValid(res);	MemoryContextReset(gv->opCtx);	return res;}static voidgistDeleteSubtree(GistVacuum *gv, BlockNumber blkno){	Buffer		buffer;	Page		page;	buffer = ReadBufferWithStrategy(gv->index, blkno, gv->strategy);	LockBuffer(buffer, GIST_EXCLUSIVE);	page = (Page) BufferGetPage(buffer);	if (!GistPageIsLeaf(page))	{		int			i;		for (i = FirstOffsetNumber; i <= PageGetMaxOffsetNumber(page); i = OffsetNumberNext(i))		{			ItemId		iid = PageGetItemId(page, i);			IndexTuple	idxtuple = (IndexTuple) PageGetItem(page, iid);			gistDeleteSubtree(gv, ItemPointerGetBlockNumber(&(idxtuple->t_tid)));		}	}	START_CRIT_SECTION();	MarkBufferDirty(buffer);	page = (Page) BufferGetPage(buffer);	GistPageSetDeleted(page);	gv->result->std.pages_deleted++;	if (!gv->index->rd_istemp)	{		XLogRecData rdata[2];		XLogRecPtr	recptr;		gistxlogPageDelete xlrec;		xlrec.node = gv->index->rd_node;		xlrec.blkno = blkno;		rdata[0].buffer = buffer;		rdata[0].buffer_std = true;		rdata[0].data = NULL;		rdata[0].len = 0;		rdata[0].next = &(rdata[1]);		rdata[1].buffer = InvalidBuffer;		rdata[1].data = (char *) &xlrec;		rdata[1].len = sizeof(gistxlogPageDelete);		rdata[1].next = NULL;		recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_DELETE, rdata);		PageSetLSN(page, recptr);		PageSetTLI(page, ThisTimeLineID);	}	else		PageSetLSN(page, XLogRecPtrForTemp);	END_CRIT_SECTION();	UnlockReleaseBuffer(buffer);}static PageGistPageGetCopyPage(Page page){	Size		pageSize = PageGetPageSize(page);	Page		tmppage;	tmppage = (Page) palloc(pageSize);	memcpy(tmppage, page, pageSize);	return tmppage;}static ArrayTuplevacuumSplitPage(GistVacuum *gv, Page tempPage, Buffer buffer, IndexTuple *addon, int curlenaddon){	ArrayTuple	res = {NULL, 0, false};	IndexTuple *vec;	SplitedPageLayout *dist = NULL,			   *ptr;	int			i,				veclen = 0;	BlockNumber blkno = BufferGetBlockNumber(buffer);	MemoryContext oldCtx = MemoryContextSwitchTo(gv->opCtx);	vec = gistextractpage(tempPage, &veclen);	vec = gistjoinvector(vec, &veclen, addon, curlenaddon);	dist = gistSplit(gv->index, tempPage, vec, veclen, &(gv->giststate));	MemoryContextSwitchTo(oldCtx);	if (blkno != GIST_ROOT_BLKNO)	{		/* if non-root split then we should not allocate new buffer */		dist->buffer = buffer;		dist->page = tempPage;		/* during vacuum we never split leaf page */		GistPageGetOpaque(dist->page)->flags = 0;	}	else		pfree(tempPage);	res.itup = (IndexTuple *) palloc(sizeof(IndexTuple) * veclen);	res.ituplen = 0;	/* make new pages and fills them */	for (ptr = dist; ptr; ptr = ptr->next)	{		char	   *data;		if (ptr->buffer == InvalidBuffer)		{			ptr->buffer = gistNewBuffer(gv->index);			GISTInitBuffer(ptr->buffer, 0);			ptr->page = BufferGetPage(ptr->buffer);		}		ptr->block.blkno = BufferGetBlockNumber(ptr->buffer);		data = (char *) (ptr->list);		for (i = 0; i < ptr->block.num; i++)		{			if (PageAddItem(ptr->page, (Item) data, IndexTupleSize((IndexTuple) data), i + FirstOffsetNumber, false, false) == InvalidOffsetNumber)				elog(ERROR, "failed to add item to index page in \"%s\"", RelationGetRelationName(gv->index));			data += IndexTupleSize((IndexTuple) data);		}		ItemPointerSetBlockNumber(&(ptr->itup->t_tid), ptr->block.blkno);		res.itup[res.ituplen] = (IndexTuple) palloc(IndexTupleSize(ptr->itup));		memcpy(res.itup[res.ituplen], ptr->itup, IndexTupleSize(ptr->itup));		res.ituplen++;	}	START_CRIT_SECTION();	for (ptr = dist; ptr; ptr = ptr->next)	{		MarkBufferDirty(ptr->buffer);		GistPageGetOpaque(ptr->page)->rightlink = InvalidBlockNumber;	}	/* restore splitted non-root page */	if (blkno != GIST_ROOT_BLKNO)	{		PageRestoreTempPage(dist->page, BufferGetPage(dist->buffer));		dist->page = BufferGetPage(dist->buffer);	}	if (!gv->index->rd_istemp)	{		XLogRecPtr	recptr;		XLogRecData *rdata;		ItemPointerData key;	/* set key for incomplete insert */		char	   *xlinfo;		ItemPointerSet(&key, blkno, TUPLE_IS_VALID);		rdata = formSplitRdata(gv->index->rd_node, blkno,							   false, &key, dist);		xlinfo = rdata->data;		recptr = XLogInsert(RM_GIST_ID, XLOG_GIST_PAGE_SPLIT, rdata);		for (ptr = dist; ptr; ptr = ptr->next)		{			PageSetLSN(BufferGetPage(ptr->buffer), recptr);			PageSetTLI(BufferGetPage(ptr->buffer), ThisTimeLineID);		}		pfree(xlinfo);		pfree(rdata);	}	else	{		for (ptr = dist; ptr; ptr = ptr->next)			PageSetLSN(BufferGetPage(ptr->buffer), XLogRecPtrForTemp);	}	for (ptr = dist; ptr; ptr = ptr->next)	{		/* we must keep the buffer pin on the head page */		if (BufferGetBlockNumber(ptr->buffer) != blkno)			UnlockReleaseBuffer(ptr->buffer);	}	if (blkno == GIST_ROOT_BLKNO)	{		ItemPointerData key;	/* set key for incomplete insert */		ItemPointerSet(&key, blkno, TUPLE_IS_VALID);		gistnewroot(gv->index, buffer, res.itup, res.ituplen, &key);	}	END_CRIT_SECTION();	MemoryContextReset(gv->opCtx);	return res;}static ArrayTuplegistVacuumUpdate(GistVacuum *gv, BlockNumber blkno, bool needunion){	ArrayTuple	res = {NULL, 0, false};	Buffer		buffer;	Page		page,				tempPage = NULL;	OffsetNumber i,				maxoff;	ItemId		iid;	int			lenaddon = 4,				curlenaddon = 0,				nOffToDelete = 0,				nBlkToDelete = 0;	IndexTuple	idxtuple,			   *addon = NULL;	bool		needwrite = false;	OffsetNumber offToDelete[MaxOffsetNumber];	BlockNumber blkToDelete[MaxOffsetNumber];	ItemPointerData *completed = NULL;	int			ncompleted = 0,				lencompleted = 16;	vacuum_delay_point();	buffer = ReadBufferWithStrategy(gv->index, blkno, gv->strategy);	LockBuffer(buffer, GIST_EXCLUSIVE);	gistcheckpage(gv->index, buffer);	page = (Page) BufferGetPage(buffer);	maxoff = PageGetMaxOffsetNumber(page);	if (GistPageIsLeaf(page))	{		if (GistTuplesDeleted(page))			needunion = needwrite = true;	}	else	{		completed = (ItemPointerData *) palloc(sizeof(ItemPointerData) * lencompleted);		addon = (IndexTuple *) palloc(sizeof(IndexTuple) * lenaddon);		/* get copy of page to work */		tempPage = GistPageGetCopyPage(page);		for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))		{			ArrayTuple	chldtuple;			bool		needchildunion;			iid = PageGetItemId(tempPage, i);			idxtuple = (IndexTuple) PageGetItem(tempPage, iid);			needchildunion = (GistTupleIsInvalid(idxtuple)) ? true : false;			if (needchildunion)				elog(DEBUG2, "gistVacuumUpdate: need union for block %u",					 ItemPointerGetBlockNumber(&(idxtuple->t_tid)));			chldtuple = gistVacuumUpdate(gv, ItemPointerGetBlockNumber(&(idxtuple->t_tid)),										 needchildunion);			if (chldtuple.ituplen || chldtuple.emptypage)			{				/* update tuple or/and inserts new */				if (chldtuple.emptypage)					blkToDelete[nBlkToDelete++] = ItemPointerGetBlockNumber(&(idxtuple->t_tid));				offToDelete[nOffToDelete++] = i;				PageIndexTupleDelete(tempPage, i);				i--;				maxoff--;				needwrite = needunion = true;				if (chldtuple.ituplen)				{					Assert(chldtuple.emptypage == false);					while (curlenaddon + chldtuple.ituplen >= lenaddon)					{						lenaddon *= 2;						addon = (IndexTuple *) repalloc(addon, sizeof(IndexTuple) * lenaddon);					}					memcpy(addon + curlenaddon, chldtuple.itup, chldtuple.ituplen * sizeof(IndexTuple));					curlenaddon += chldtuple.ituplen;					if (chldtuple.ituplen > 1)					{						/*						 * child was split, so we need mark completion						 * insert(split)						 */						int			j;						while (ncompleted + chldtuple.ituplen > lencompleted)						{							lencompleted *= 2;							completed = (ItemPointerData *) repalloc(completed, sizeof(ItemPointerData) * lencompleted);						}						for (j = 0; j < chldtuple.ituplen; j++)						{							ItemPointerCopy(&(chldtuple.itup[j]->t_tid), completed + ncompleted);							ncompleted++;						}					}					pfree(chldtuple.itup);				}			}		}		Assert(maxoff == PageGetMaxOffsetNumber(tempPage));		if (curlenaddon)		{			/* insert updated tuples */			if (gistnospace(tempPage, addon, curlenaddon, InvalidOffsetNumber, 0))			{				/* there is no space on page to insert tuples */				res = vacuumSplitPage(gv, tempPage, buffer, addon, curlenaddon);				tempPage = NULL;	/* vacuumSplitPage() free tempPage */				needwrite = needunion = false;	/* gistSplit already forms												 * unions and writes pages */			}			else				/* enough free space */				gistfillbuffer(gv->index, tempPage, addon, curlenaddon, InvalidOffsetNumber);		}	}	/*	 * If page is empty, we should remove pointer to it before deleting page	 * (except root)	 */	if (blkno != GIST_ROOT_BLKNO && (PageIsEmpty(page) || (tempPage && PageIsEmpty(tempPage))))	{		/*		 * New version of page is empty, so leave it unchanged, upper call

⌨️ 快捷键说明

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