heapam.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 2,410 行 · 第 1/5 页

C
2,410
字号
 * XXX	might be better to do direct access instead of *		using the generality of heapgettup(). * * XXX It is very possible that when a scan is restored, that a tuple * XXX which previously qualified may fail for time range purposes, unless * XXX some form of locking exists (ie., portals currently can act funny. * ---------------- */voidheap_restrpos(HeapScanDesc scan){	/* XXX no amrestrpos checking that ammarkpos called */	/* Note: no locking manipulations needed */	/*	 * unpin scan buffers	 */	if (BufferIsValid(scan->rs_cbuf))		ReleaseBuffer(scan->rs_cbuf);	scan->rs_cbuf = InvalidBuffer;	if (!ItemPointerIsValid(&scan->rs_mctid))	{		scan->rs_ctup.t_datamcxt = NULL;		scan->rs_ctup.t_data = NULL;	}	else	{		scan->rs_ctup.t_self = scan->rs_mctid;		scan->rs_ctup.t_datamcxt = NULL;		scan->rs_ctup.t_data = (HeapTupleHeader) 0x1;	/* for heapgettup */		heapgettup(scan->rs_rd,				   0,				   &(scan->rs_ctup),				   &(scan->rs_cbuf),				   scan->rs_snapshot,				   0,				   (ScanKey) NULL);	}}XLogRecPtrlog_heap_clean(Relation reln, Buffer buffer, OffsetNumber *unused, int uncnt){	xl_heap_clean xlrec;	XLogRecPtr	recptr;	XLogRecData rdata[2];	/* Caller should not call me on a temp relation */	Assert(!reln->rd_istemp);	xlrec.node = reln->rd_node;	xlrec.block = BufferGetBlockNumber(buffer);	rdata[0].buffer = InvalidBuffer;	rdata[0].data = (char *) &xlrec;	rdata[0].len = SizeOfHeapClean;	rdata[0].next = &(rdata[1]);	/*	 * The unused-offsets array is not actually in the buffer, but pretend	 * that it is.	When XLogInsert stores the whole buffer, the offsets	 * array need not be stored too.	 */	rdata[1].buffer = buffer;	if (uncnt > 0)	{		rdata[1].data = (char *) unused;		rdata[1].len = uncnt * sizeof(OffsetNumber);	}	else	{		rdata[1].data = NULL;		rdata[1].len = 0;	}	rdata[1].next = NULL;	recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CLEAN, rdata);	return (recptr);}static XLogRecPtrlog_heap_update(Relation reln, Buffer oldbuf, ItemPointerData from,				Buffer newbuf, HeapTuple newtup, bool move){	/*	 * Note: xlhdr is declared to have adequate size and correct alignment	 * for an xl_heap_header.  However the two tids, if present at all,	 * will be packed in with no wasted space after the xl_heap_header;	 * they aren't necessarily aligned as implied by this struct	 * declaration.	 */	struct	{		xl_heap_header hdr;		TransactionId tid1;		TransactionId tid2;	}			xlhdr;	int			hsize = SizeOfHeapHeader;	xl_heap_update xlrec;	XLogRecPtr	recptr;	XLogRecData rdata[4];	Page		page = BufferGetPage(newbuf);	uint8		info = (move) ? XLOG_HEAP_MOVE : XLOG_HEAP_UPDATE;	/* Caller should not call me on a temp relation */	Assert(!reln->rd_istemp);	xlrec.target.node = reln->rd_node;	xlrec.target.tid = from;	xlrec.newtid = newtup->t_self;	rdata[0].buffer = InvalidBuffer;	rdata[0].data = (char *) &xlrec;	rdata[0].len = SizeOfHeapUpdate;	rdata[0].next = &(rdata[1]);	rdata[1].buffer = oldbuf;	rdata[1].data = NULL;	rdata[1].len = 0;	rdata[1].next = &(rdata[2]);	xlhdr.hdr.t_natts = newtup->t_data->t_natts;	xlhdr.hdr.t_infomask = newtup->t_data->t_infomask;	xlhdr.hdr.t_hoff = newtup->t_data->t_hoff;	if (move)					/* remember xmax & xmin */	{		TransactionId xid[2];	/* xmax, xmin */		if (newtup->t_data->t_infomask & (HEAP_XMAX_INVALID |										  HEAP_MARKED_FOR_UPDATE))			xid[0] = InvalidTransactionId;		else			xid[0] = HeapTupleHeaderGetXmax(newtup->t_data);		xid[1] = HeapTupleHeaderGetXmin(newtup->t_data);		memcpy((char *) &xlhdr + hsize,			   (char *) xid,			   2 * sizeof(TransactionId));		hsize += 2 * sizeof(TransactionId);	}	/*	 * As with insert records, we need not store the rdata[2] segment if	 * we decide to store the whole buffer instead.	 */	rdata[2].buffer = newbuf;	rdata[2].data = (char *) &xlhdr;	rdata[2].len = hsize;	rdata[2].next = &(rdata[3]);	rdata[3].buffer = newbuf;	/* PG73FORMAT: write bitmap [+ padding] [+ oid] + data */	rdata[3].data = (char *) newtup->t_data + offsetof(HeapTupleHeaderData, t_bits);	rdata[3].len = newtup->t_len - offsetof(HeapTupleHeaderData, t_bits);	rdata[3].next = NULL;	/* If new tuple is the single and first tuple on page... */	if (ItemPointerGetOffsetNumber(&(newtup->t_self)) == FirstOffsetNumber &&		PageGetMaxOffsetNumber(page) == FirstOffsetNumber)	{		info |= XLOG_HEAP_INIT_PAGE;		rdata[2].buffer = rdata[3].buffer = InvalidBuffer;	}	recptr = XLogInsert(RM_HEAP_ID, info, rdata);	return (recptr);}XLogRecPtrlog_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,			  Buffer newbuf, HeapTuple newtup){	return (log_heap_update(reln, oldbuf, from, newbuf, newtup, true));}static voidheap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record){	xl_heap_clean *xlrec = (xl_heap_clean *) XLogRecGetData(record);	Relation	reln;	Buffer		buffer;	Page		page;	if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))		return;	reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->node);	if (!RelationIsValid(reln))		return;	buffer = XLogReadBuffer(false, reln, xlrec->block);	if (!BufferIsValid(buffer))		elog(PANIC, "heap_clean_redo: no block");	page = (Page) BufferGetPage(buffer);	if (PageIsNew((PageHeader) page))		elog(PANIC, "heap_clean_redo: uninitialized page");	if (XLByteLE(lsn, PageGetLSN(page)))	{		UnlockAndReleaseBuffer(buffer);		return;	}	if (record->xl_len > SizeOfHeapClean)	{		OffsetNumber *unused;		OffsetNumber *unend;		ItemId		lp;		unused = (OffsetNumber *) ((char *) xlrec + SizeOfHeapClean);		unend = (OffsetNumber *) ((char *) xlrec + record->xl_len);		while (unused < unend)		{			lp = PageGetItemId(page, *unused + 1);			lp->lp_flags &= ~LP_USED;			unused++;		}	}	PageRepairFragmentation(page, NULL);	PageSetLSN(page, lsn);	PageSetSUI(page, ThisStartUpID);	/* prev sui */	UnlockAndWriteBuffer(buffer);}static voidheap_xlog_delete(bool redo, XLogRecPtr lsn, XLogRecord *record){	xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record);	Relation	reln;	Buffer		buffer;	Page		page;	OffsetNumber offnum;	ItemId		lp = NULL;	HeapTupleHeader htup;	if (redo && (record->xl_info & XLR_BKP_BLOCK_1))		return;	reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node);	if (!RelationIsValid(reln))		return;	buffer = XLogReadBuffer(false, reln,						ItemPointerGetBlockNumber(&(xlrec->target.tid)));	if (!BufferIsValid(buffer))		elog(PANIC, "heap_delete_%sdo: no block", (redo) ? "re" : "un");	page = (Page) BufferGetPage(buffer);	if (PageIsNew((PageHeader) page))		elog(PANIC, "heap_delete_%sdo: uninitialized page", (redo) ? "re" : "un");	if (redo)	{		if (XLByteLE(lsn, PageGetLSN(page)))	/* changes are applied */		{			UnlockAndReleaseBuffer(buffer);			return;		}	}	else if (XLByteLT(PageGetLSN(page), lsn))	/* changes are not applied												 * ?! */		elog(PANIC, "heap_delete_undo: bad page LSN");	offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));	if (PageGetMaxOffsetNumber(page) >= offnum)		lp = PageGetItemId(page, offnum);	if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))		elog(PANIC, "heap_delete_%sdo: invalid lp", (redo) ? "re" : "un");	htup = (HeapTupleHeader) PageGetItem(page, lp);	if (redo)	{		htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |							  HEAP_XMAX_INVALID |							  HEAP_MARKED_FOR_UPDATE |							  HEAP_MOVED);		HeapTupleHeaderSetXmax(htup, record->xl_xid);		HeapTupleHeaderSetCmax(htup, FirstCommandId);		/* Make sure there is no forward chain link in t_ctid */		htup->t_ctid = xlrec->target.tid;		PageSetLSN(page, lsn);		PageSetSUI(page, ThisStartUpID);		UnlockAndWriteBuffer(buffer);		return;	}	elog(PANIC, "heap_delete_undo: unimplemented");}static voidheap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record){	xl_heap_insert *xlrec = (xl_heap_insert *) XLogRecGetData(record);	Relation	reln;	Buffer		buffer;	Page		page;	OffsetNumber offnum;	if (redo && (record->xl_info & XLR_BKP_BLOCK_1))		return;	reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node);	if (!RelationIsValid(reln))		return;	buffer = XLogReadBuffer((redo) ? true : false, reln,						ItemPointerGetBlockNumber(&(xlrec->target.tid)));	if (!BufferIsValid(buffer))		return;	page = (Page) BufferGetPage(buffer);	if (PageIsNew((PageHeader) page) &&		(!redo || !(record->xl_info & XLOG_HEAP_INIT_PAGE)))		elog(PANIC, "heap_insert_%sdo: uninitialized page", (redo) ? "re" : "un");	if (redo)	{		struct		{			HeapTupleHeaderData hdr;			char		data[MaxTupleSize];		}			tbuf;		HeapTupleHeader htup;		xl_heap_header xlhdr;		uint32		newlen;		if (record->xl_info & XLOG_HEAP_INIT_PAGE)			PageInit(page, BufferGetPageSize(buffer), 0);		if (XLByteLE(lsn, PageGetLSN(page)))	/* changes are applied */		{			UnlockAndReleaseBuffer(buffer);			return;		}		offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));		if (PageGetMaxOffsetNumber(page) + 1 < offnum)			elog(PANIC, "heap_insert_redo: invalid max offset number");		newlen = record->xl_len - SizeOfHeapInsert - SizeOfHeapHeader;		Assert(newlen <= MaxTupleSize);		memcpy((char *) &xlhdr,			   (char *) xlrec + SizeOfHeapInsert,			   SizeOfHeapHeader);		htup = &tbuf.hdr;		MemSet((char *) htup, 0, sizeof(HeapTupleHeaderData));		/* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */		memcpy((char *) htup + offsetof(HeapTupleHeaderData, t_bits),			   (char *) xlrec + SizeOfHeapInsert + SizeOfHeapHeader,			   newlen);		newlen += offsetof(HeapTupleHeaderData, t_bits);		htup->t_natts = xlhdr.t_natts;		htup->t_infomask = xlhdr.t_infomask;		htup->t_hoff = xlhdr.t_hoff;		HeapTupleHeaderSetXmin(htup, record->xl_xid);		HeapTupleHeaderSetCmin(htup, FirstCommandId);		htup->t_ctid = xlrec->target.tid;		offnum = PageAddItem(page, (Item) htup, newlen, offnum,							 LP_USED | OverwritePageMode);		if (offnum == InvalidOffsetNumber)			elog(PANIC, "heap_insert_redo: failed to add tuple");		PageSetLSN(page, lsn);		PageSetSUI(page, ThisStartUpID);		/* prev sui */		UnlockAndWriteBuffer(buffer);		return;	}	/* undo insert */	if (XLByteLT(PageGetLSN(page), lsn))		/* changes are not applied												 * ?! */		elog(PANIC, "heap_insert_undo: bad page LSN");	elog(PANIC, "heap_insert_undo: unimplemented");}/* * Handles UPDATE & MOVE */static voidheap_xlog_update(bool redo, XLogRecPtr lsn, XLogRecord *record, bool move){	xl_heap_update *xlrec = (xl_heap_update *) XLogRecGetData(record);	Relation	reln = XLogOpenRelation(redo, RM_HEAP_ID, xlrec->target.node);	Buffer		buffer;	bool		samepage =	(ItemPointerGetBlockNumber(&(xlrec->newtid)) ==	 ItemPointerGetBlockNumber(&(xlrec->target.tid)));	Page		page;	OffsetNumber offnum;	ItemId		lp = NULL;	HeapTupleHeader htup;	if (!RelationIsValid(reln))		return;	if (redo && (record->xl_info & XLR_BKP_BLOCK_1))		goto newt;	/* Deal with old tuple version */	buffer = XLogReadBuffer(false, reln,						ItemPointerGetBlockNumber(&(xlrec->target.tid)));	if (!BufferIsValid(buffer))		elog(PANIC, "heap_update_%sdo: no block", (redo) ? "re" : "un");	page = (Page) BufferGetPage(buffer);	if (PageIsNew((PageHeader) page))		elog(PANIC, "heap_update_%sdo: uninitialized old page", (redo) ? "re" : "un");	if (redo)	{		if (XLByteLE(lsn, PageGetLSN(page)))	/* changes are applied */		{			UnlockAndReleaseBuffer(buffer);			if (samepage)				return;			goto newt;		}	}	else if (XLByteLT(PageGetLSN(page), lsn))	/* changes are not applied												 * ?! */		elog(PANIC, "heap_update_undo: bad old tuple page LSN");	offnum = ItemPointerGetOffsetNumber(&(xlrec->target.tid));	if (PageGetMaxOffsetNumber(page) >= offnum)		lp = PageGetItemId(page, offnum);	if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsUsed(lp))		elog(PANIC, "heap_update_%sdo: invalid lp", (redo) ? "re" : "un");	htup = (HeapTupleHeader) PageGetItem(page, lp);	if (redo)	{		if (move)		{			htup->t_infomask &= ~(HEAP_XMIN_COMMITTED |								  HEAP_XMIN_INVALID |								  HEAP_MOVED_IN);			htup->t_infomask |= HEAP_MOVED_OFF;			HeapTupleHeaderSetXvac(htup, record->xl_xid);			/* Make sure there is no forward chain link in t_ctid */			htup->t_ctid = xlrec->target.tid;		}		else		{			htup->t_infomask &= ~(HEAP_XMAX_COMMITTED |								  HEAP_XMAX_INVALID |								  HEAP_MARKED_FOR_UPDATE |								  HEAP_MOVED);			HeapTupleHeaderSetXmax(htup, record->xl_xid);			HeapTupleHeaderSetCmax(htup, FirstCommandId);			/* Set forward chain link in t_ctid */			htup->t_ctid = xlrec->newtid;		}		if (samepage)			goto newsame;		PageSetLSN(page, lsn);		PageSetSUI(page, ThisStartUpID);		UnlockAndWriteBuffer(buffer);		goto newt;	}	elog(PANIC, "heap_update_undo: unimplemented");	/* Deal with new tuple */newt:;	if (redo &&		((record->xl_info & XLR_BKP_BLOC

⌨️ 快捷键说明

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