mirror of
https://github.com/postgres/postgres.git
synced 2025-08-21 10:42:50 +03:00
Add built-in userlock manipulation functions to replace the former
contrib functionality. Along the way, remove the USER_LOCKS configuration symbol, since it no longer makes any sense to try to compile that out. No user documentation yet ... mmoncure has promised to write some. Thanks to Abhijit Menon-Sen for creating a first draft to work from.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.20 2006/07/23 23:08:46 tgl Exp $
|
||||
$PostgreSQL: pgsql/src/backend/storage/lmgr/README,v 1.21 2006/09/18 22:40:36 tgl Exp $
|
||||
|
||||
|
||||
LOCKING OVERVIEW
|
||||
@@ -48,7 +48,7 @@ The rest of this README file discusses the regular lock manager in detail.
|
||||
LOCK DATA STRUCTURES
|
||||
|
||||
Lock methods describe the overall locking behavior. Currently there are
|
||||
two lock methods: DEFAULT and USER. (USER locks are non-blocking.)
|
||||
two lock methods: DEFAULT and USER.
|
||||
|
||||
Lock modes describe the type of the lock (read/write or shared/exclusive).
|
||||
In principle, each lock method can have its own set of lock modes with
|
||||
@@ -502,11 +502,6 @@ level by someone.
|
||||
User locks and normal locks are completely orthogonal and they don't
|
||||
interfere with each other.
|
||||
|
||||
User locks are always non blocking, therefore they are never acquired if
|
||||
already held by another process. They must be released explicitly by the
|
||||
application but they are released automatically when a backend terminates.
|
||||
|
||||
The lockmode parameter can have the same values as for normal locks although
|
||||
probably only ExclusiveLock can have some practical use.
|
||||
|
||||
DZ - 22 Nov 1997
|
||||
User locks are always held as session locks, so that they are not released at
|
||||
transaction end. They must be released explicitly by the application --- but
|
||||
they are released automatically when a backend terminates.
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.41 2006/07/23 23:08:46 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/deadlock.c,v 1.42 2006/09/18 22:40:36 tgl Exp $
|
||||
*
|
||||
* Interface:
|
||||
*
|
||||
@@ -873,9 +873,11 @@ DescribeLockTag(StringInfo buf, const LOCKTAG *lock)
|
||||
break;
|
||||
case LOCKTAG_USERLOCK:
|
||||
appendStringInfo(buf,
|
||||
_("user lock [%u,%u]"),
|
||||
_("user lock [%u,%u,%u,%u]"),
|
||||
lock->locktag_field1,
|
||||
lock->locktag_field2);
|
||||
lock->locktag_field2,
|
||||
lock->locktag_field3,
|
||||
lock->locktag_field4);
|
||||
break;
|
||||
default:
|
||||
appendStringInfo(buf,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.172 2006/08/27 19:14:34 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.173 2006/09/18 22:40:36 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* A lock table is a shared memory hash table. When
|
||||
@@ -127,8 +127,6 @@ static const LockMethodData default_lockmethod = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef USER_LOCKS
|
||||
|
||||
static const LockMethodData user_lockmethod = {
|
||||
AccessExclusiveLock, /* highest valid lock mode number */
|
||||
false,
|
||||
@@ -141,17 +139,13 @@ static const LockMethodData user_lockmethod = {
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* USER_LOCKS */
|
||||
|
||||
/*
|
||||
* map from lock method id to the lock table data structures
|
||||
*/
|
||||
static const LockMethod LockMethods[] = {
|
||||
NULL,
|
||||
&default_lockmethod,
|
||||
#ifdef USER_LOCKS
|
||||
&user_lockmethod
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@@ -1,20 +1,21 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* lockfuncs.c
|
||||
* Set-returning functions to view the state of locks within the DB.
|
||||
* Functions for SQL access to various lock-manager capabilities.
|
||||
*
|
||||
* Copyright (c) 2002-2006, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.24 2006/07/23 23:08:46 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.25 2006/09/18 22:40:37 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "funcapi.h"
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "funcapi.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/proc.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
@@ -266,3 +267,256 @@ pg_lock_status(PG_FUNCTION_ARGS)
|
||||
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Functions for manipulating USERLOCK locks
|
||||
*
|
||||
* We make use of the locktag fields as follows:
|
||||
*
|
||||
* field1: MyDatabaseId ... ensures locks are local to each database
|
||||
* field2: first of 2 int4 keys, or high-order half of an int8 key
|
||||
* field3: second of 2 int4 keys, or low-order half of an int8 key
|
||||
* field4: 1 if using an int8 key, 2 if using 2 int4 keys
|
||||
*/
|
||||
#define SET_LOCKTAG_INT64(tag, key64) \
|
||||
SET_LOCKTAG_USERLOCK(tag, \
|
||||
MyDatabaseId, \
|
||||
(uint32) ((key64) >> 32), \
|
||||
(uint32) (key64), \
|
||||
1)
|
||||
#define SET_LOCKTAG_INT32(tag, key1, key2) \
|
||||
SET_LOCKTAG_USERLOCK(tag, MyDatabaseId, key1, key2, 2)
|
||||
|
||||
/*
|
||||
* pg_advisory_lock(int8) - acquire exclusive lock on an int8 key
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_lock_int8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 key = PG_GETARG_INT64(0);
|
||||
LOCKTAG tag;
|
||||
|
||||
SET_LOCKTAG_INT64(tag, key);
|
||||
|
||||
(void) LockAcquire(&tag, ExclusiveLock, true, false);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_lock_shared(int8) - acquire share lock on an int8 key
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 key = PG_GETARG_INT64(0);
|
||||
LOCKTAG tag;
|
||||
|
||||
SET_LOCKTAG_INT64(tag, key);
|
||||
|
||||
(void) LockAcquire(&tag, ShareLock, true, false);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_try_advisory_lock(int8) - acquire exclusive lock on an int8 key, no wait
|
||||
*
|
||||
* Returns true if successful, false if lock not available
|
||||
*/
|
||||
Datum
|
||||
pg_try_advisory_lock_int8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 key = PG_GETARG_INT64(0);
|
||||
LOCKTAG tag;
|
||||
LockAcquireResult res;
|
||||
|
||||
SET_LOCKTAG_INT64(tag, key);
|
||||
|
||||
res = LockAcquire(&tag, ExclusiveLock, true, true);
|
||||
|
||||
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_try_advisory_lock_shared(int8) - acquire share lock on an int8 key, no wait
|
||||
*
|
||||
* Returns true if successful, false if lock not available
|
||||
*/
|
||||
Datum
|
||||
pg_try_advisory_lock_shared_int8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 key = PG_GETARG_INT64(0);
|
||||
LOCKTAG tag;
|
||||
LockAcquireResult res;
|
||||
|
||||
SET_LOCKTAG_INT64(tag, key);
|
||||
|
||||
res = LockAcquire(&tag, ShareLock, true, true);
|
||||
|
||||
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_unlock(int8) - release exclusive lock on an int8 key
|
||||
*
|
||||
* Returns true if successful, false if lock was not held
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_unlock_int8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 key = PG_GETARG_INT64(0);
|
||||
LOCKTAG tag;
|
||||
bool res;
|
||||
|
||||
SET_LOCKTAG_INT64(tag, key);
|
||||
|
||||
res = LockRelease(&tag, ExclusiveLock, true);
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_unlock_shared(int8) - release share lock on an int8 key
|
||||
*
|
||||
* Returns true if successful, false if lock was not held
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_unlock_shared_int8(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 key = PG_GETARG_INT64(0);
|
||||
LOCKTAG tag;
|
||||
bool res;
|
||||
|
||||
SET_LOCKTAG_INT64(tag, key);
|
||||
|
||||
res = LockRelease(&tag, ShareLock, true);
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_lock_int4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 key1 = PG_GETARG_INT32(0);
|
||||
int32 key2 = PG_GETARG_INT32(1);
|
||||
LOCKTAG tag;
|
||||
|
||||
SET_LOCKTAG_INT32(tag, key1, key2);
|
||||
|
||||
(void) LockAcquire(&tag, ExclusiveLock, true, false);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 key1 = PG_GETARG_INT32(0);
|
||||
int32 key2 = PG_GETARG_INT32(1);
|
||||
LOCKTAG tag;
|
||||
|
||||
SET_LOCKTAG_INT32(tag, key1, key2);
|
||||
|
||||
(void) LockAcquire(&tag, ShareLock, true, false);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_try_advisory_lock(int4, int4) - acquire exclusive lock on 2 int4 keys, no wait
|
||||
*
|
||||
* Returns true if successful, false if lock not available
|
||||
*/
|
||||
Datum
|
||||
pg_try_advisory_lock_int4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 key1 = PG_GETARG_INT32(0);
|
||||
int32 key2 = PG_GETARG_INT32(1);
|
||||
LOCKTAG tag;
|
||||
LockAcquireResult res;
|
||||
|
||||
SET_LOCKTAG_INT32(tag, key1, key2);
|
||||
|
||||
res = LockAcquire(&tag, ExclusiveLock, true, true);
|
||||
|
||||
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_try_advisory_lock_shared(int4, int4) - acquire share lock on 2 int4 keys, no wait
|
||||
*
|
||||
* Returns true if successful, false if lock not available
|
||||
*/
|
||||
Datum
|
||||
pg_try_advisory_lock_shared_int4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 key1 = PG_GETARG_INT32(0);
|
||||
int32 key2 = PG_GETARG_INT32(1);
|
||||
LOCKTAG tag;
|
||||
LockAcquireResult res;
|
||||
|
||||
SET_LOCKTAG_INT32(tag, key1, key2);
|
||||
|
||||
res = LockAcquire(&tag, ShareLock, true, true);
|
||||
|
||||
PG_RETURN_BOOL(res != LOCKACQUIRE_NOT_AVAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_unlock(int4, int4) - release exclusive lock on 2 int4 keys
|
||||
*
|
||||
* Returns true if successful, false if lock was not held
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_unlock_int4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 key1 = PG_GETARG_INT32(0);
|
||||
int32 key2 = PG_GETARG_INT32(1);
|
||||
LOCKTAG tag;
|
||||
bool res;
|
||||
|
||||
SET_LOCKTAG_INT32(tag, key1, key2);
|
||||
|
||||
res = LockRelease(&tag, ExclusiveLock, true);
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_unlock_shared(int4, int4) - release share lock on 2 int4 keys
|
||||
*
|
||||
* Returns true if successful, false if lock was not held
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_unlock_shared_int4(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 key1 = PG_GETARG_INT32(0);
|
||||
int32 key2 = PG_GETARG_INT32(1);
|
||||
LOCKTAG tag;
|
||||
bool res;
|
||||
|
||||
SET_LOCKTAG_INT32(tag, key1, key2);
|
||||
|
||||
res = LockRelease(&tag, ShareLock, true);
|
||||
|
||||
PG_RETURN_BOOL(res);
|
||||
}
|
||||
|
||||
/*
|
||||
* pg_advisory_unlock_all() - release all userlocks
|
||||
*/
|
||||
Datum
|
||||
pg_advisory_unlock_all(PG_FUNCTION_ARGS)
|
||||
{
|
||||
LockReleaseAll(USER_LOCKMETHOD, true);
|
||||
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.169 2006/07/13 16:49:18 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.170 2006/09/18 22:40:38 tgl Exp $
|
||||
*
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
@@ -554,9 +554,7 @@ ShutdownPostgres(int code, Datum arg)
|
||||
* User locks are not released by transaction end, so be sure to release
|
||||
* them explicitly.
|
||||
*/
|
||||
#ifdef USER_LOCKS
|
||||
LockReleaseAll(USER_LOCKMETHOD, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user