aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/storage/lmgr/README15
-rw-r--r--src/backend/storage/lmgr/deadlock.c8
-rw-r--r--src/backend/storage/lmgr/lock.c8
-rw-r--r--src/backend/utils/adt/lockfuncs.c260
-rw-r--r--src/backend/utils/init/postinit.c4
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
}