SET_LOCKTAG_USERLOCK(tag, id1, id2);
- return LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
- lockmode, true);
+ return (LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId,
+ lockmode, true) != LOCKACQUIRE_NOT_AVAIL);
}
int
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.74 2005/05/19 21:35:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.75 2005/05/29 22:45:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
LockRelation(Relation relation, LOCKMODE lockmode)
{
LOCKTAG tag;
+ LockAcquireResult res;
SET_LOCKTAG_RELATION(tag,
relation->rd_lockInfo.lockRelId.dbId,
relation->rd_lockInfo.lockRelId.relId);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ res = LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, 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.
+ * rebuild it and not just delete it. We can skip this if the lock
+ * was already held, however.
*/
- RelationIncrementReferenceCount(relation);
- AcceptInvalidationMessages();
- RelationDecrementReferenceCount(relation);
+ if (res != LOCKACQUIRE_ALREADY_HELD)
+ {
+ RelationIncrementReferenceCount(relation);
+ AcceptInvalidationMessages();
+ RelationDecrementReferenceCount(relation);
+ }
}
/*
ConditionalLockRelation(Relation relation, LOCKMODE lockmode)
{
LOCKTAG tag;
+ LockAcquireResult res;
SET_LOCKTAG_RELATION(tag,
relation->rd_lockInfo.lockRelId.dbId,
relation->rd_lockInfo.lockRelId.relId);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, true))
+ res = LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, true);
+
+ if (res == LOCKACQUIRE_NOT_AVAIL)
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.
+ * rebuild it and not just delete it. We can skip this if the lock
+ * was already held, however.
*/
- RelationIncrementReferenceCount(relation);
- AcceptInvalidationMessages();
- RelationDecrementReferenceCount(relation);
+ if (res != LOCKACQUIRE_ALREADY_HELD)
+ {
+ RelationIncrementReferenceCount(relation);
+ AcceptInvalidationMessages();
+ RelationDecrementReferenceCount(relation);
+ }
return true;
}
SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
- if (!LockAcquire(LockTableId, &tag, InvalidTransactionId,
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, InvalidTransactionId,
+ lockmode, false);
}
/*
relation->rd_lockInfo.lockRelId.dbId,
relation->rd_lockInfo.lockRelId.relId);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
relation->rd_lockInfo.lockRelId.relId,
blkno);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
relation->rd_lockInfo.lockRelId.relId,
blkno);
- return LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, true);
+ return (LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, true) != LOCKACQUIRE_NOT_AVAIL);
}
/*
ItemPointerGetBlockNumber(tid),
ItemPointerGetOffsetNumber(tid));
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
SET_LOCKTAG_TRANSACTION(tag, xid);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- ExclusiveLock, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ ExclusiveLock, false);
}
/*
SET_LOCKTAG_TRANSACTION(tag, xid);
- if (!LockAcquire(LockTableId, &tag, myxid, ShareLock, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, myxid,
+ ShareLock, false);
+
LockRelease(LockTableId, &tag, myxid, ShareLock);
if (!TransactionIdIsInProgress(xid))
objid,
objsubid);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
objid,
objsubid);
- if (!LockAcquire(LockTableId, &tag, GetTopTransactionId(),
- lockmode, false))
- elog(ERROR, "LockAcquire failed");
+ (void) LockAcquire(LockTableId, &tag, GetTopTransactionId(),
+ lockmode, false);
}
/*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.153 2005/05/29 04:23:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.154 2005/05/29 22:45:02 tgl Exp $
*
* NOTES
* Outside modules can create a lock table and acquire/release
static void RemoveLocalLock(LOCALLOCK *locallock);
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
-static int WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
- ResourceOwner owner);
+static void WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
+ ResourceOwner owner);
static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
int *myHolding);
static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
* LockAcquire -- Check for lock conflicts, sleep if conflict found,
* set lock if/when no conflicts.
*
- * Returns: TRUE if lock was acquired, FALSE otherwise. Note that
- * a FALSE return is to be expected if dontWait is TRUE;
- * but if dontWait is FALSE, only a parameter error can cause
- * a FALSE return. (XXX probably we should just ereport on parameter
- * errors, instead of conflating this with failure to acquire lock?)
+ * Returns one of:
+ * LOCKACQUIRE_NOT_AVAIL lock not available, and dontWait=true
+ * LOCKACQUIRE_OK lock successfully acquired
+ * LOCKACQUIRE_ALREADY_HELD incremented count for lock already held
+ *
+ * In the normal case where dontWait=false and the caller doesn't need to
+ * distinguish a freshly acquired lock from one already taken earlier in
+ * this same transaction, there is no need to examine the return value.
*
* Side Effects: The lock is acquired and recorded in lock tables.
*
*
* DZ - 22 Nov 1997
*/
-
-bool
+LockAcquireResult
LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode, bool dontWait)
{
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
- {
- elog(WARNING, "bad lock table id: %d", lockmethodid);
- return FALSE;
- }
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
/* Session locks and user locks are not transactional */
if (xid != InvalidTransactionId &&
if (locallock->nLocks > 0)
{
GrantLockLocal(locallock, owner);
- return TRUE;
+ return LOCKACQUIRE_ALREADY_HELD;
}
/*
GrantLockLocal(locallock, owner);
PROCLOCK_PRINT("LockAcquire: my other XID owning", proclock);
LWLockRelease(masterLock);
- return TRUE;
+ return LOCKACQUIRE_ALREADY_HELD;
}
/*
/*
* We can't acquire the lock immediately. If caller specified no
- * blocking, remove useless table entries and return FALSE without
- * waiting.
+ * blocking, remove useless table entries and return NOT_AVAIL
+ * without waiting.
*/
if (dontWait)
{
LWLockRelease(masterLock);
if (locallock->nLocks == 0)
RemoveLocalLock(locallock);
- return FALSE;
+ return LOCKACQUIRE_NOT_AVAIL;
}
/*
/*
* Sleep till someone wakes me up.
*/
- status = WaitOnLock(lockmethodid, locallock, owner);
+ WaitOnLock(lockmethodid, locallock, owner);
/*
* NOTE: do not do any material change of state between here and
LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
/* Should we retry ? */
LWLockRelease(masterLock);
- return FALSE;
+ elog(ERROR, "LockAcquire failed");
}
PROCLOCK_PRINT("LockAcquire: granted", proclock);
LOCK_PRINT("LockAcquire: granted", lock, lockmode);
LWLockRelease(masterLock);
- return status == STATUS_OK;
+ return LOCKACQUIRE_OK;
}
/*
*
* The locktable's masterLock must be held at entry.
*/
-static int
+static void
WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
ResourceOwner owner)
{
LOCK_PRINT("WaitOnLock: wakeup on lock",
locallock->lock, locallock->tag.mode);
- return STATUS_OK;
}
/*
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
- elog(ERROR, "bad lock method: %d", lockmethodid);
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
/*
* Find the LOCALLOCK entry for this lock and lockmode
Assert(lockmethodid < NumLockMethods);
lockMethodTable = LockMethods[lockmethodid];
if (!lockMethodTable)
- elog(ERROR, "bad lock method: %d", lockmethodid);
+ elog(ERROR, "unrecognized lock method: %d", lockmethodid);
numLockModes = lockMethodTable->numLockModes;
masterLock = lockMethodTable->masterLock;
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.86 2005/05/19 23:30:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/lock.h,v 1.87 2005/05/29 22:45:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
} LockData;
+/* Result codes for LockAcquire() */
+typedef enum
+{
+ LOCKACQUIRE_NOT_AVAIL, /* lock not available, and dontWait=true */
+ LOCKACQUIRE_OK, /* lock successfully acquired */
+ LOCKACQUIRE_ALREADY_HELD /* incremented count for lock already held */
+} LockAcquireResult;
+
+
/*
* function s
*/
const LOCKMASK *conflictsP,
int numModes, int maxBackends);
extern LOCKMETHODID LockMethodTableRename(LOCKMETHODID lockmethodid);
-extern bool LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
+extern LockAcquireResult LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode, bool dontWait);
extern bool LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
TransactionId xid, LOCKMODE lockmode);