summaryrefslogtreecommitdiff
path: root/src/backend/access
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2005-08-01 20:31:16 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2005-08-01 20:31:16 +0000
commit2a4fad1a0e43d6375ffa8eddb2d8dfa1ed36593f (patch)
treebb2bc2208507b0ab2403850e8dd01003a4ed73e9 /src/backend/access
parentca7abcd89dbeecb82cde50fccf4f6c483244fdf7 (diff)
downloadpostgresql-2a4fad1a0e43d6375ffa8eddb2d8dfa1ed36593f.tar.gz
Add NOWAIT option to SELECT FOR UPDATE/SHARE.
Original patch by Hans-Juergen Schoenig, revisions by Karel Zak and Tom Lane.
Diffstat (limited to 'src/backend/access')
-rw-r--r--src/backend/access/heap/heapam.c39
-rw-r--r--src/backend/access/transam/multixact.c41
2 files changed, 73 insertions, 7 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 843b2909ef..c5851765f2 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.195 2005/06/20 18:37:01 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.196 2005/08/01 20:31:05 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -1945,7 +1945,7 @@ simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
*/
HTSU_Result
heap_lock_tuple(Relation relation, HeapTuple tuple, Buffer *buffer,
- CommandId cid, LockTupleMode mode)
+ CommandId cid, LockTupleMode mode, bool nowait)
{
HTSU_Result result;
ItemPointer tid = &(tuple->t_self);
@@ -1998,7 +1998,16 @@ l3:
*/
if (!have_tuple_lock)
{
- LockTuple(relation, tid, tuple_lock_type);
+ if (nowait)
+ {
+ if (!ConditionalLockTuple(relation, tid, tuple_lock_type))
+ ereport(ERROR,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("could not obtain lock on row in relation \"%s\"",
+ RelationGetRelationName(relation))));
+ }
+ else
+ LockTuple(relation, tid, tuple_lock_type);
have_tuple_lock = true;
}
@@ -2020,7 +2029,17 @@ l3:
else if (infomask & HEAP_XMAX_IS_MULTI)
{
/* wait for multixact to end */
- MultiXactIdWait((MultiXactId) xwait);
+ if (nowait)
+ {
+ if (!ConditionalMultiXactIdWait((MultiXactId) xwait))
+ ereport(ERROR,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("could not obtain lock on row in relation \"%s\"",
+ RelationGetRelationName(relation))));
+ }
+ else
+ MultiXactIdWait((MultiXactId) xwait);
+
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/*
@@ -2045,7 +2064,17 @@ l3:
else
{
/* wait for regular transaction to end */
- XactLockTableWait(xwait);
+ if (nowait)
+ {
+ if (!ConditionalXactLockTableWait(xwait))
+ ereport(ERROR,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("could not obtain lock on row in relation \"%s\"",
+ RelationGetRelationName(relation))));
+ }
+ else
+ XactLockTableWait(xwait);
+
LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
/*
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 41773625af..8f107d42c6 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -42,7 +42,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.5 2005/06/08 15:50:25 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.6 2005/08/01 20:31:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -559,6 +559,43 @@ MultiXactIdWait(MultiXactId multi)
}
/*
+ * ConditionalMultiXactIdWait
+ * As above, but only lock if we can get the lock without blocking.
+ */
+bool
+ConditionalMultiXactIdWait(MultiXactId multi)
+{
+ bool result = true;
+ TransactionId *members;
+ int nmembers;
+
+ nmembers = GetMultiXactIdMembers(multi, &members);
+
+ if (nmembers >= 0)
+ {
+ int i;
+
+ for (i = 0; i < nmembers; i++)
+ {
+ TransactionId member = members[i];
+
+ debug_elog4(DEBUG2, "ConditionalMultiXactIdWait: trying %d (%u)",
+ i, member);
+ if (!TransactionIdIsCurrentTransactionId(member))
+ {
+ result = ConditionalXactLockTableWait(member);
+ if (!result)
+ break;
+ }
+ }
+
+ pfree(members);
+ }
+
+ return result;
+}
+
+/*
* CreateMultiXactId
* Make a new MultiXactId
*
@@ -590,7 +627,7 @@ CreateMultiXactId(int nxids, TransactionId *xids)
*/
multi = mXactCacheGetBySet(nxids, xids);
if (MultiXactIdIsValid(multi))
- {
+ {
debug_elog2(DEBUG2, "Create: in cache!");
return multi;
}