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

📄 lmgr.c

📁 PostgreSQL7.4.6 for Linux
💻 C
字号:
/*------------------------------------------------------------------------- * * lmgr.c *	  POSTGRES lock manager code * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lmgr.c,v 1.60 2003/09/04 22:06:27 tgl Exp $ * *------------------------------------------------------------------------- */#include "postgres.h"#include "access/transam.h"#include "access/xact.h"#include "catalog/catalog.h"#include "miscadmin.h"#include "storage/lmgr.h"#include "utils/inval.h"static LOCKMASK LockConflicts[] = {	0,	/* AccessShareLock */	(1 << AccessExclusiveLock),	/* RowShareLock */	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),	/* RowExclusiveLock */	(1 << ShareLock) | (1 << ShareRowExclusiveLock) |	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),	/* ShareUpdateExclusiveLock */	(1 << ShareUpdateExclusiveLock) |	(1 << ShareLock) | (1 << ShareRowExclusiveLock) |	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),	/* ShareLock */	(1 << RowExclusiveLock) | (1 << ShareUpdateExclusiveLock) |	(1 << ShareRowExclusiveLock) |	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),	/* ShareRowExclusiveLock */	(1 << RowExclusiveLock) | (1 << ShareUpdateExclusiveLock) |	(1 << ShareLock) | (1 << ShareRowExclusiveLock) |	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),	/* ExclusiveLock */	(1 << RowShareLock) |	(1 << RowExclusiveLock) | (1 << ShareUpdateExclusiveLock) |	(1 << ShareLock) | (1 << ShareRowExclusiveLock) |	(1 << ExclusiveLock) | (1 << AccessExclusiveLock),	/* AccessExclusiveLock */	(1 << AccessShareLock) | (1 << RowShareLock) |	(1 << RowExclusiveLock) | (1 << ShareUpdateExclusiveLock) |	(1 << ShareLock) | (1 << ShareRowExclusiveLock) |	(1 << ExclusiveLock) | (1 << AccessExclusiveLock)};LOCKMETHOD	LockTableId = (LOCKMETHOD) NULL;LOCKMETHOD	LongTermTableId = (LOCKMETHOD) NULL;/* * Create the lock table described by LockConflicts */LOCKMETHODInitLockTable(int maxBackends){	int			lockmethod;	/* number of lock modes is lengthof()-1 because of dummy zero */	lockmethod = LockMethodTableInit("LockTable",									 LockConflicts,									 lengthof(LockConflicts) - 1,									 maxBackends);	LockTableId = lockmethod;	if (!(LockTableId))		elog(ERROR, "could not initialize lock table");#ifdef USER_LOCKS	/*	 * Allocate another tableId for long-term locks	 */	LongTermTableId = LockMethodTableRename(LockTableId);	if (!(LongTermTableId))		elog(ERROR, "could not rename long-term lock table");#endif	return LockTableId;}/* * RelationInitLockInfo *		Initializes the lock information in a relation descriptor. * *		relcache.c must call this during creation of any reldesc. */voidRelationInitLockInfo(Relation relation){	Assert(RelationIsValid(relation));	Assert(OidIsValid(RelationGetRelid(relation)));	relation->rd_lockInfo.lockRelId.relId = RelationGetRelid(relation);	if (relation->rd_rel->relisshared)		relation->rd_lockInfo.lockRelId.dbId = InvalidOid;	else		relation->rd_lockInfo.lockRelId.dbId = MyDatabaseId;}/* *		LockRelation */voidLockRelation(Relation relation, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relation->rd_lockInfo.lockRelId.relId;	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;	tag.objId.blkno = InvalidBlockNumber;	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),					 lockmode, false))		elog(ERROR, "LockAcquire failed");	/*	 * Check to see if the relcache entry has been invalidated while we	 * were waiting to lock it.  If so, rebuild it, or ereport() trying.	 * Increment the refcount to ensure that RelationFlushRelation will	 * rebuild it and not just delete it.	 */	RelationIncrementReferenceCount(relation);	AcceptInvalidationMessages();	RelationDecrementReferenceCount(relation);}/* *		ConditionalLockRelation * * As above, but only lock if we can get the lock without blocking. * Returns TRUE iff the lock was acquired. * * NOTE: we do not currently need conditional versions of all the * LockXXX routines in this file, but they could easily be added if needed. */boolConditionalLockRelation(Relation relation, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relation->rd_lockInfo.lockRelId.relId;	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;	tag.objId.blkno = InvalidBlockNumber;	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),					 lockmode, true))		return false;	/*	 * Check to see if the relcache entry has been invalidated while we	 * were waiting to lock it.  If so, rebuild it, or ereport() trying.	 * Increment the refcount to ensure that RelationFlushRelation will	 * rebuild it and not just delete it.	 */	RelationIncrementReferenceCount(relation);	AcceptInvalidationMessages();	RelationDecrementReferenceCount(relation);	return true;}/* *		UnlockRelation */voidUnlockRelation(Relation relation, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relation->rd_lockInfo.lockRelId.relId;	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;	tag.objId.blkno = InvalidBlockNumber;	LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);}/* *		LockRelationForSession * * This routine grabs a session-level lock on the target relation.	The * session lock persists across transaction boundaries.  It will be removed * when UnlockRelationForSession() is called, or if an ereport(ERROR) occurs, * or if the backend exits. * * Note that one should also grab a transaction-level lock on the rel * in any transaction that actually uses the rel, to ensure that the * relcache entry is up to date. */voidLockRelationForSession(LockRelId *relid, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relid->relId;	tag.dbId = relid->dbId;	tag.objId.blkno = InvalidBlockNumber;	if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,					 lockmode, false))		elog(ERROR, "LockAcquire failed");}/* *		UnlockRelationForSession */voidUnlockRelationForSession(LockRelId *relid, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relid->relId;	tag.dbId = relid->dbId;	tag.objId.blkno = InvalidBlockNumber;	LockRelease(LockTableId, &tag, InvalidTransactionId, lockmode);}/* *		LockPage * * Obtain a page-level lock.  This is currently used by some index access * methods to lock index pages.  For heap relations, it is used only with * blkno == 0 to signify locking the relation for extension. */voidLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relation->rd_lockInfo.lockRelId.relId;	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;	tag.objId.blkno = blkno;	if (!LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),					 lockmode, false))		elog(ERROR, "LockAcquire failed");}/* *		ConditionalLockPage * * As above, but only lock if we can get the lock without blocking. * Returns TRUE iff the lock was acquired. */boolConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relation->rd_lockInfo.lockRelId.relId;	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;	tag.objId.blkno = blkno;	return LockAcquire(LockTableId, &tag, GetCurrentTransactionId(),					   lockmode, true);}/* *		UnlockPage */voidUnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = relation->rd_lockInfo.lockRelId.relId;	tag.dbId = relation->rd_lockInfo.lockRelId.dbId;	tag.objId.blkno = blkno;	LockRelease(LockTableId, &tag, GetCurrentTransactionId(), lockmode);}/* *		XactLockTableInsert * * Insert a lock showing that the given transaction ID is running --- * this is done during xact startup.  The lock can then be used to wait * for the transaction to finish. * * We need no corresponding unlock function, since the lock will always * be released implicitly at transaction commit/abort, never any other way. */voidXactLockTableInsert(TransactionId xid){	LOCKTAG		tag;	MemSet(&tag, 0, sizeof(tag));	tag.relId = XactLockTableId;	tag.dbId = InvalidOid;		/* xids are globally unique */	tag.objId.xid = xid;	if (!LockAcquire(LockTableId, &tag, xid,					 ExclusiveLock, false))		elog(ERROR, "LockAcquire failed");}/* *		XactLockTableWait * * Wait for the specified transaction to commit or abort. */voidXactLockTableWait(TransactionId xid){	LOCKTAG		tag;	TransactionId myxid = GetCurrentTransactionId();	Assert(!TransactionIdEquals(xid, myxid));	MemSet(&tag, 0, sizeof(tag));	tag.relId = XactLockTableId;	tag.dbId = InvalidOid;	tag.objId.xid = xid;	if (!LockAcquire(LockTableId, &tag, myxid,					 ShareLock, false))		elog(ERROR, "LockAcquire failed");	LockRelease(LockTableId, &tag, myxid, ShareLock);	/*	 * Transaction was committed/aborted/crashed - we have to update	 * pg_clog if transaction is still marked as running.	 */	if (!TransactionIdDidCommit(xid) && !TransactionIdDidAbort(xid))		TransactionIdAbort(xid);}

⌨️ 快捷键说明

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