6cc842abd3
level" locks. A session lock is not released at transaction commit (but it is released on transaction abort, to ensure recovery after an elog(ERROR)). In VACUUM, use a session lock to protect the master table while vacuuming a TOAST table, so that the TOAST table can be done in an independent transaction. I also took this opportunity to do some cleanup and renaming in the lock code. The previously noted bug in ProcLockWakeup, that it couldn't wake up any waiters beyond the first non-wakeable waiter, is now fixed. Also found a previously unknown bug of the same kind (failure to scan all members of a lock queue in some cases) in DeadLockCheck. This might have led to failure to detect a deadlock condition, resulting in indefinite waits, but it's difficult to characterize the conditions required to trigger a failure.
104 lines
2.0 KiB
C
104 lines
2.0 KiB
C
/*
|
|
* user_locks.c --
|
|
*
|
|
* This loadable module, together with my user-lock.patch applied to the
|
|
* backend, provides support for user-level long-term cooperative locks.
|
|
*
|
|
* Copyright (C) 1999, Massimo Dal Zotto <dz@cs.unitn.it>
|
|
*
|
|
* This software is distributed under the GNU General Public License
|
|
* either version 2, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "postgres.h"
|
|
#include "miscadmin.h"
|
|
#include "storage/lmgr.h"
|
|
#include "storage/proc.h"
|
|
#include "utils/elog.h"
|
|
|
|
#include "user_locks.h"
|
|
|
|
int
|
|
user_lock(uint32 id1, uint32 id2, LOCKMODE lockmode)
|
|
{
|
|
LOCKTAG tag;
|
|
|
|
memset(&tag, 0, sizeof(LOCKTAG));
|
|
tag.dbId = MyDatabaseId;
|
|
tag.relId = 0;
|
|
tag.objId.blkno = (BlockNumber) id2;
|
|
tag.offnum = (OffsetNumber) (id1 & 0xffff);
|
|
|
|
return LockAcquire(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
|
|
}
|
|
|
|
int
|
|
user_unlock(uint32 id1, uint32 id2, LOCKMODE lockmode)
|
|
{
|
|
LOCKTAG tag;
|
|
|
|
memset(&tag, 0, sizeof(LOCKTAG));
|
|
tag.dbId = MyDatabaseId;
|
|
tag.relId = 0;
|
|
tag.objId.blkno = (BlockNumber) id2;
|
|
tag.offnum = (OffsetNumber) (id1 & 0xffff);
|
|
|
|
return LockRelease(USER_LOCKMETHOD, &tag, InvalidTransactionId, lockmode);
|
|
}
|
|
|
|
int
|
|
user_write_lock(uint32 id1, uint32 id2)
|
|
{
|
|
return user_lock(id1, id2, ExclusiveLock);
|
|
}
|
|
|
|
|
|
int
|
|
user_write_unlock(uint32 id1, uint32 id2)
|
|
{
|
|
return user_unlock(id1, id2, ExclusiveLock);
|
|
}
|
|
|
|
int
|
|
user_write_lock_oid(Oid oid)
|
|
{
|
|
return user_lock(0, oid, ExclusiveLock);
|
|
}
|
|
|
|
int
|
|
user_write_unlock_oid(Oid oid)
|
|
{
|
|
return user_unlock(0, oid, ExclusiveLock);
|
|
}
|
|
|
|
int
|
|
user_unlock_all()
|
|
{
|
|
PROC *proc;
|
|
SHMEM_OFFSET location;
|
|
|
|
ShmemPIDLookup(MyProcPid, &location);
|
|
if (location == INVALID_OFFSET)
|
|
{
|
|
elog(NOTICE, "UserUnlockAll: unable to get proc ptr");
|
|
return -1;
|
|
}
|
|
|
|
proc = (PROC *) MAKE_PTR(location);
|
|
return LockReleaseAll(USER_LOCKMETHOD, proc, false, InvalidTransactionId);
|
|
}
|
|
|
|
/* end of file */
|
|
|
|
/*
|
|
* Local Variables:
|
|
* tab-width: 4
|
|
* c-indent-level: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
*/
|