mirror of
https://github.com/postgres/postgres.git
synced 2025-11-06 07:49:08 +03:00
Invent ResourceOwner mechanism as per my recent proposal, and use it to
keep track of portal-related resources separately from transaction-related resources. This allows cursors to work in a somewhat sane fashion with nested transactions. For now, cursor behavior is non-subtransactional, that is a cursor's state does not roll back if you abort a subtransaction that fetched from the cursor. We might want to change that later.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.134 2004/07/01 00:50:59 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.135 2004/07/17 03:28:51 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@@ -30,14 +30,15 @@
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "access/xact.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/memutils.h"
|
||||
#include "utils/ps_status.h"
|
||||
#include "utils/resowner.h"
|
||||
|
||||
|
||||
/* This configuration variable is used to set the lock table size */
|
||||
@@ -424,6 +425,9 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
locktag->lockmethodid = lockmethodid;
|
||||
|
||||
/* Prepare to record the lock in the current resource owner */
|
||||
ResourceOwnerEnlargeLocks(CurrentResourceOwner);
|
||||
|
||||
Assert(lockmethodid < NumLockMethods);
|
||||
lockMethodTable = LockMethods[lockmethodid];
|
||||
if (!lockMethodTable)
|
||||
@@ -567,6 +571,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
if (proclock->holding[lockmode] > 0)
|
||||
{
|
||||
GrantLock(lock, proclock, lockmode);
|
||||
ResourceOwnerRememberLock(CurrentResourceOwner, locktag, xid,
|
||||
lockmode);
|
||||
PROCLOCK_PRINT("LockAcquire: owning", proclock);
|
||||
LWLockRelease(masterLock);
|
||||
return TRUE;
|
||||
@@ -580,6 +586,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
if (myHolding[lockmode] > 0)
|
||||
{
|
||||
GrantLock(lock, proclock, lockmode);
|
||||
ResourceOwnerRememberLock(CurrentResourceOwner, locktag, xid,
|
||||
lockmode);
|
||||
PROCLOCK_PRINT("LockAcquire: my other XID owning", proclock);
|
||||
LWLockRelease(masterLock);
|
||||
return TRUE;
|
||||
@@ -601,6 +609,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
{
|
||||
/* No conflict with held or previously requested locks */
|
||||
GrantLock(lock, proclock, lockmode);
|
||||
ResourceOwnerRememberLock(CurrentResourceOwner, locktag, xid,
|
||||
lockmode);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -803,6 +813,9 @@ LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc, int *myHolding)
|
||||
*
|
||||
* NOTE: if proc was blocked, it also needs to be removed from the wait list
|
||||
* and have its waitLock/waitHolder fields cleared. That's not done here.
|
||||
*
|
||||
* NOTE: the lock also has to be recorded in the current ResourceOwner;
|
||||
* but since we may be awaking some other process, we can't do that here.
|
||||
*/
|
||||
void
|
||||
GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
|
||||
@@ -964,6 +977,9 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/* ???????? This must be changed when short term locks will be used */
|
||||
locktag->lockmethodid = lockmethodid;
|
||||
|
||||
/* Record release of the lock in the current resource owner */
|
||||
ResourceOwnerForgetLock(CurrentResourceOwner, locktag, xid, lockmode);
|
||||
|
||||
Assert(lockmethodid < NumLockMethods);
|
||||
lockMethodTable = LockMethods[lockmethodid];
|
||||
if (!lockMethodTable)
|
||||
@@ -1134,20 +1150,15 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
*
|
||||
* Well, not necessarily *all* locks. The available behaviors are:
|
||||
*
|
||||
* which == ReleaseAll: release all locks regardless of transaction
|
||||
* allxids == true: release all locks regardless of transaction
|
||||
* affiliation.
|
||||
*
|
||||
* which == ReleaseAllExceptSession: release all locks with Xid != 0
|
||||
* allxids == false: release all locks with Xid != 0
|
||||
* (zero is the Xid used for "session" locks).
|
||||
*
|
||||
* which == ReleaseGivenXids: release only locks whose Xids appear in
|
||||
* the xids[] array (of length nxids).
|
||||
*
|
||||
* xids/nxids are ignored when which != ReleaseGivenXids.
|
||||
*/
|
||||
bool
|
||||
LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc,
|
||||
LockReleaseWhich which, int nxids, TransactionId *xids)
|
||||
bool allxids)
|
||||
{
|
||||
SHM_QUEUE *procHolders = &(proc->procHolders);
|
||||
PROCLOCK *proclock;
|
||||
@@ -1196,25 +1207,9 @@ LockReleaseAll(LOCKMETHODID lockmethodid, PGPROC *proc,
|
||||
if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
|
||||
goto next_item;
|
||||
|
||||
if (which == ReleaseGivenXids)
|
||||
{
|
||||
/* Ignore locks with an Xid not in the list */
|
||||
bool release = false;
|
||||
|
||||
for (i = 0; i < nxids; i++)
|
||||
{
|
||||
if (TransactionIdEquals(proclock->tag.xid, xids[i]))
|
||||
{
|
||||
release = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!release)
|
||||
goto next_item;
|
||||
}
|
||||
/* Ignore locks with Xid=0 unless we are asked to release All locks */
|
||||
else if (TransactionIdEquals(proclock->tag.xid, InvalidTransactionId)
|
||||
&& which != ReleaseAll)
|
||||
/* Ignore locks with Xid=0 unless we are asked to release all locks */
|
||||
if (TransactionIdEquals(proclock->tag.xid, InvalidTransactionId)
|
||||
&& !allxids)
|
||||
goto next_item;
|
||||
|
||||
PROCLOCK_PRINT("LockReleaseAll", proclock);
|
||||
|
||||
Reference in New Issue
Block a user