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

📄 transsup.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * transsup.c *	  postgres transaction access method support code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/access/transam/transsup.c,v 1.21.2.2 1999/08/02 05:56:46 scrappy Exp $ * * NOTES *	  This file contains support functions for the high *	  level access method interface routines found in transam.c * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/xact.h"#include "utils/bit.h"static XidStatus TransBlockGetXidStatus(Block tblock,					   TransactionId transactionId);static void TransBlockSetXidStatus(Block tblock,					   TransactionId transactionId, XidStatus xstatus);/* ---------------------------------------------------------------- *					  general support routines * ---------------------------------------------------------------- *//* -------------------------------- *		AmiTransactionOverride * *		This function is used to manipulate the bootstrap flag. * -------------------------------- */voidAmiTransactionOverride(bool flag){	AMI_OVERRIDE = flag;}/* -------------------------------- *		TransComputeBlockNumber * -------------------------------- */voidTransComputeBlockNumber(Relation relation,		/* relation to test */						TransactionId transactionId,	/* transaction id to														 * test */						BlockNumber *blockNumberOutP){	long		itemsPerBlock = 0;	/* ----------------	 *	we calculate the block number of our transaction	 *	by dividing the transaction id by the number of	 *	transaction things per block.	 * ----------------	 */	if (relation == LogRelation)		itemsPerBlock = TP_NumXidStatusPerBlock;	else		elog(ERROR, "TransComputeBlockNumber: unknown relation");	/* ----------------	 *	warning! if the transaction id's get too large	 *	then a BlockNumber may not be large enough to hold the results	 *	of our division.	 *	 *	XXX  this will all vanish soon when we implement an improved	 *		 transaction id schema -cim 3/23/90	 *	 *	This has vanished now that xid's are 4 bytes (no longer 5).	 *	-mer 5/24/92	 * ----------------	 */	(*blockNumberOutP) = transactionId / itemsPerBlock;}/* ---------------------------------------------------------------- *					 trans block support routines * ---------------------------------------------------------------- *//* -------------------------------- *		TransBlockGetLastTransactionIdStatus * *		This returns the status and transaction id of the last *		transaction information recorded on the given TransBlock. * -------------------------------- */#ifdef NOT_USEDstatic XidStatusTransBlockGetLastTransactionIdStatus(Block tblock,									 TransactionId baseXid,									 TransactionId *returnXidP){	Index		index;	Index		maxIndex;	bits8		bit1;	bits8		bit2;	BitIndex	offset;	XidStatus	xstatus;	/* ----------------	 *	sanity check	 * ----------------	 */	Assert((tblock != NULL));	/* ----------------	 *	search downward from the top of the block data, looking	 *	for the first Non-in progress transaction status.  Since we	 *	are scanning backward, this will be last recorded transaction	 *	status on the block.	 * ----------------	 */	maxIndex = TP_NumXidStatusPerBlock;	for (index = maxIndex; index > 0; index--)	{		offset = BitIndexOf(index - 1);		bit1 = ((bits8) BitArrayBitIsSet((BitArray) tblock, offset++)) << 1;		bit2 = (bits8) BitArrayBitIsSet((BitArray) tblock, offset);		xstatus = (bit1 | bit2);		/* ----------------		 *	here we have the status of some transaction, so test		 *	if the status is recorded as "in progress".  If so, then		 *	we save the transaction id in the place specified by the caller.		 * ----------------		 */		if (xstatus != XID_INPROGRESS)		{			if (returnXidP != NULL)			{				TransactionIdStore(baseXid, returnXidP);				TransactionIdAdd(returnXidP, index - 1);			}			break;		}	}	/* ----------------	 *	if we get here and index is 0 it means we couldn't find	 *	a non-inprogress transaction on the block.	For now we just	 *	return this info to the user.  They can check if the return	 *	status is "in progress" to know this condition has arisen.	 * ----------------	 */	if (index == 0)	{		if (returnXidP != NULL)			TransactionIdStore(baseXid, returnXidP);	}	/* ----------------	 *	return the status to the user	 * ----------------	 */	return xstatus;}#endif/* -------------------------------- *		TransBlockGetXidStatus * *		This returns the status of the desired transaction * -------------------------------- */static XidStatusTransBlockGetXidStatus(Block tblock,					   TransactionId transactionId){	Index		index;	bits8		bit1;	bits8		bit2;	BitIndex	offset;	/* ----------------	 *	calculate the index into the transaction data where	 *	our transaction status is located	 *	 *	XXX this will be replaced soon when we move to the	 *		new transaction id scheme -cim 3/23/90	 *	 *	The old system has now been replaced. -mer 5/24/92	 * ----------------	 */	index = transactionId % TP_NumXidStatusPerBlock;	/* ----------------	 *	get the data at the specified index	 * ----------------	 */	offset = BitIndexOf(index);	bit1 = ((bits8) BitArrayBitIsSet((BitArray) tblock, offset++)) << 1;	bit2 = (bits8) BitArrayBitIsSet((BitArray) tblock, offset);	/* ----------------	 *	return the transaction status to the caller	 * ----------------	 */	return (XidStatus) (bit1 | bit2);}/* -------------------------------- *		TransBlockSetXidStatus * *		This sets the status of the desired transaction * -------------------------------- */static voidTransBlockSetXidStatus(Block tblock,					   TransactionId transactionId,					   XidStatus xstatus){	Index		index;	BitIndex	offset;	/* ----------------	 *	calculate the index into the transaction data where	 *	we sould store our transaction status.	 *	 *	XXX this will be replaced soon when we move to the	 *		new transaction id scheme -cim 3/23/90	 *	 *	The new scheme is here -mer 5/24/92	 * ----------------	 */	index = transactionId % TP_NumXidStatusPerBlock;	offset = BitIndexOf(index);	/* ----------------	 *	store the transaction value at the specified offset	 * ----------------	 */	switch (xstatus)	{		case XID_COMMIT:		/* set 10 */			BitArraySetBit((BitArray) tblock, offset);			BitArrayClearBit((BitArray) tblock, offset + 1);			break;		case XID_ABORT: /* set 01 */			BitArrayClearBit((BitArray) tblock, offset);			BitArraySetBit((BitArray) tblock, offset + 1);			break;		case XID_INPROGRESS:	/* set 00 */			BitArrayClearBit((BitArray) tblock, offset);			BitArrayClearBit((BitArray) tblock, offset + 1);			break;		default:			elog(NOTICE,				 "TransBlockSetXidStatus: invalid status: %d (ignored)",				 xstatus);			break;	}}/* ---------------------------------------------------------------- *				   transam i/o support routines * ---------------------------------------------------------------- *//* -------------------------------- *		TransBlockNumberGetXidStatus * -------------------------------- */XidStatusTransBlockNumberGetXidStatus(Relation relation,							 BlockNumber blockNumber,							 TransactionId xid,							 bool *failP){	Buffer		buffer;			/* buffer associated with block */	Block		block;			/* block containing xstatus */	XidStatus	xstatus;		/* recorded status of xid */	bool		localfail;		/* bool used if failP = NULL */	/* ----------------	 *	get the page containing the transaction information	 * ----------------	 */	buffer = ReadBuffer(relation, blockNumber);	LockBuffer(buffer, BUFFER_LOCK_SHARE);	block = BufferGetBlock(buffer);	/* ----------------	 *	get the status from the block.	note, for now we always	 *	return false in failP.	 * ----------------	 */	if (failP == NULL)		failP = &localfail;	(*failP) = false;	xstatus = TransBlockGetXidStatus(block, xid);	/* ----------------	 *	release the buffer and return the status	 * ----------------	 */	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);	ReleaseBuffer(buffer);	return xstatus;}/* -------------------------------- *		TransBlockNumberSetXidStatus * -------------------------------- */voidTransBlockNumberSetXidStatus(Relation relation,							 BlockNumber blockNumber,							 TransactionId xid,							 XidStatus xstatus,							 bool *failP){	Buffer		buffer;			/* buffer associated with block */	Block		block;			/* block containing xstatus */	bool		localfail;		/* bool used if failP = NULL */	/* ----------------	 *	get the block containing the transaction status	 * ----------------	 */	buffer = ReadBuffer(relation, blockNumber);	LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);	block = BufferGetBlock(buffer);	/* ----------------	 *	attempt to update the status of the transaction on the block.	 *	if we are successful, write the block. otherwise release the buffer.	 *	note, for now we always return false in failP.	 * ----------------	 */	if (failP == NULL)		failP = &localfail;	(*failP) = false;	TransBlockSetXidStatus(block, xid, xstatus);	LockBuffer(buffer, BUFFER_LOCK_UNLOCK);	if ((*failP) == false)		WriteBuffer(buffer);	else		ReleaseBuffer(buffer);}/* -------------------------------- *		TransGetLastRecordedTransaction * -------------------------------- */#ifdef NOT_USEDvoidTransGetLastRecordedTransaction(Relation relation,								TransactionId xid,		/* return: transaction														 * id */								bool *failP){	BlockNumber blockNumber;	/* block number */	Buffer		buffer;			/* buffer associated with block */	Block		block;			/* block containing xid status */	BlockNumber n;				/* number of blocks in the relation */	TransactionId baseXid;	(*failP) = false;	/* ----------------	 *	SOMEDAY gain exclusive access to the log relation	 *	 *	That someday is today 5 Aug. 1991 -mer	 *	It looks to me like we only need to set a read lock here, despite	 *	the above comment about exclusive access.  The block is never	 *	actually written into, we only check status bits.	 * ----------------	 */	RelationSetLockForRead(relation);	/* ----------------	 *	we assume the last block of the log contains the last	 *	recorded transaction.  If the relation is empty we return	 *	failure to the user.	 * ----------------	 */	n = RelationGetNumberOfBlocks(relation);	if (n == 0)	{		(*failP) = true;		return;	}	/* ----------------	 *	get the block containing the transaction information	 * ----------------	 */	blockNumber = n - 1;	buffer = ReadBuffer(relation, blockNumber);	block = BufferGetBlock(buffer);	/* ----------------	 *	get the last xid on the block	 * ----------------	 */	baseXid = blockNumber * TP_NumXidStatusPerBlock;/* XXX ???? xid won't get returned! - AY '94 */	TransBlockGetLastTransactionIdStatus(block, baseXid, &xid);	ReleaseBuffer(buffer);	/* ----------------	 *	SOMEDAY release our lock on the log relation	 * ----------------	 */	RelationUnsetLockForRead(relation);}#endif

⌨️ 快捷键说明

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