diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/storage/lmgr/README | 15 | ||||
-rw-r--r-- | src/backend/storage/lmgr/deadlock.c | 8 | ||||
-rw-r--r-- | src/backend/storage/lmgr/lock.c | 8 | ||||
-rw-r--r-- | src/backend/utils/adt/lockfuncs.c | 260 | ||||
-rw-r--r-- | src/backend/utils/init/postinit.c | 4 |
5 files changed, 269 insertions, 26 deletions
diff --git a/src/backend/storage/lmgr/README b/src/backend/storage/lmgr/README index 6720a5579f5..8884676d284 100644 --- a/src/backend/storage/lmgr/README +++ b/src/backend/storage/lmgr/README @@ -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. diff --git a/src/backend/storage/lmgr/deadlock.c b/src/backend/storage/lmgr/deadlock.c index 0e4acd5c164..f75ca1da4cf 100644 --- a/src/backend/storage/lmgr/deadlock.c +++ b/src/backend/storage/lmgr/deadlock.c @@ -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, diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index c59999e20ca..6300dc2eeb4 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -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 }; diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index 40046a020a0..f7c7deca8d9 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -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(); +} diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 191082834db..6664755fd3e 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -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 } |