5-pg85-locktimeout-11-ctxdiff.patch

text/x-patch

Filename: 5-pg85-locktimeout-11-ctxdiff.patch
Type: text/x-patch
Part: 0
Message: lock_timeout GUC patch

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: context
File+
doc/src/sgml/config.sgml 24 0
doc/src/sgml/ref/lock.sgml 5 2
doc/src/sgml/ref/select.sgml 8 0
src/backend/access/gin/ginutil.c 5 1
src/backend/access/gin/ginvacuum.c 10 2
src/backend/access/gist/gistutil.c 5 1
src/backend/access/gist/gistvacuum.c 10 2
src/backend/access/hash/hashpage.c 5 1
src/backend/access/heap/heapam.c 78 26
src/backend/access/heap/hio.c 5 1
src/backend/access/heap/visibilitymap.c 5 1
src/backend/access/nbtree/nbtinsert.c 5 1
src/backend/access/nbtree/nbtpage.c 5 1
src/backend/access/nbtree/nbtree.c 5 1
src/backend/access/transam/multixact.c 10 2
src/backend/access/transam/xact.c 10 2
src/backend/catalog/dependency.c 15 3
src/backend/catalog/index.c 15 3
src/backend/catalog/pg_inherits.c 6 1
src/backend/catalog/pg_shdepend.c 5 1
src/backend/commands/dbcommands.c 11 3
src/backend/commands/indexcmds.c 20 4
src/backend/commands/lockcmds.c 18 17
src/backend/commands/sequence.c 5 1
src/backend/commands/tablecmds.c 10 2
src/backend/commands/user.c 5 1
src/backend/commands/vacuum.c 5 1
src/backend/commands/vacuumlazy.c 5 1
src/backend/executor/execMain.c 2 1
src/backend/port/posix_sema.c 43 0
src/backend/port/sysv_sema.c 90 0
src/backend/port/win32_sema.c 59 0
src/backend/storage/lmgr/lmgr.c 69 24
src/backend/storage/lmgr/lock.c 49 19
src/backend/storage/lmgr/proc.c 23 5
src/backend/utils/cache/plancache.c 15 2
src/backend/utils/cache/relcache.c 2 1
src/backend/utils/init/postinit.c 6 2
src/backend/utils/misc/guc.c 10 0
src/include/access/multixact.h 1 1
src/include/storage/lmgr.h 13 13
src/include/storage/pg_sema.h 3 0
src/include/storage/proc.h 1 0
diff -dcrpN pgsql.orig/doc/src/sgml/config.sgml pgsql.5/doc/src/sgml/config.sgml
*** pgsql.orig/doc/src/sgml/config.sgml	2010-01-06 08:43:22.000000000 +0100
--- pgsql.5/doc/src/sgml/config.sgml	2010-01-11 22:01:48.000000000 +0100
*************** COPY postgres_log FROM '/full/path/to/lo
*** 4191,4196 ****
--- 4191,4220 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="guc-lock-timeout" xreflabel="lock_timeout">
+       <term><varname>lock_timeout</varname> (<type>integer</type>)</term>
+       <indexterm>
+        <primary><varname>lock_timeout</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         Abort any statement that tries to acquire a heavy-weight lock (e.g. rows,
+         pages, tables, indices or other objects) and the lock has to wait more
+         than the specified number of milliseconds, starting from the time the
+         command arrives at the server from the client.
+         If <varname>log_min_error_statement</> is set to <literal>ERROR</> or lower,
+         the statement that timed out will also be logged. A value of zero
+         (the default) turns off the limitation.
+        </para>
+ 
+        <para>
+         Setting <varname>lock_timeout</> in
+         <filename>postgresql.conf</> is not recommended because it
+         affects all sessions.
+        </para>      
+       </listitem>   
+      </varlistentry>
+ 
       <varlistentry id="guc-vacuum-freeze-table-age" xreflabel="vacuum_freeze_table_age">
        <term><varname>vacuum_freeze_table_age</varname> (<type>integer</type>)</term>
        <indexterm>
diff -dcrpN pgsql.orig/doc/src/sgml/ref/lock.sgml pgsql.5/doc/src/sgml/ref/lock.sgml
*** pgsql.orig/doc/src/sgml/ref/lock.sgml	2009-09-18 08:26:40.000000000 +0200
--- pgsql.5/doc/src/sgml/ref/lock.sgml	2010-01-11 22:01:48.000000000 +0100
*************** LOCK [ TABLE ] [ ONLY ] <replaceable cla
*** 39,46 ****
     <literal>NOWAIT</literal> is specified, <command>LOCK
     TABLE</command> does not wait to acquire the desired lock: if it
     cannot be acquired immediately, the command is aborted and an
!    error is emitted.  Once obtained, the lock is held for the
!    remainder of the current transaction.  (There is no <command>UNLOCK
     TABLE</command> command; locks are always released at transaction
     end.)
    </para>
--- 39,49 ----
     <literal>NOWAIT</literal> is specified, <command>LOCK
     TABLE</command> does not wait to acquire the desired lock: if it
     cannot be acquired immediately, the command is aborted and an
!    error is emitted. If <varname>lock_timeout</varname> is set to a value
!    higher than 0, and the lock cannot be acquired under the specified
!    timeout value in milliseconds, the command is aborted and an error
!    is emitted. Once obtained, the lock is held for the remainder of  
!    the current transaction.  (There is no <command>UNLOCK
     TABLE</command> command; locks are always released at transaction
     end.)
    </para>
diff -dcrpN pgsql.orig/doc/src/sgml/ref/select.sgml pgsql.5/doc/src/sgml/ref/select.sgml
*** pgsql.orig/doc/src/sgml/ref/select.sgml	2009-10-29 15:23:52.000000000 +0100
--- pgsql.5/doc/src/sgml/ref/select.sgml	2010-01-11 22:01:48.000000000 +0100
*************** FOR SHARE [ OF <replaceable class="param
*** 1121,1126 ****
--- 1121,1134 ----
     </para>
  
     <para>
+     If <literal>NOWAIT</> option is not specified and <varname>lock_timeout</varname>
+     is set to a value higher than 0, and the lock needs to wait more than
+     the specified value in milliseconds, the command reports an error after
+     timing out, rather than waiting indefinitely. The note in the previous
+     paragraph applies to the <varname>lock_timeout</varname>, too.
+    </para>
+ 
+    <para>
      If specific tables are named in <literal>FOR UPDATE</literal>
      or <literal>FOR SHARE</literal>,
      then only rows coming from those tables are locked; any other
diff -dcrpN pgsql.orig/src/backend/access/gin/ginutil.c pgsql.5/src/backend/access/gin/ginutil.c
*** pgsql.orig/src/backend/access/gin/ginutil.c	2010-01-03 12:54:01.000000000 +0100
--- pgsql.5/src/backend/access/gin/ginutil.c	2010-01-11 22:01:48.000000000 +0100
*************** GinNewBuffer(Relation index)
*** 183,189 ****
  	/* Must extend the file */
  	needLock = !RELATION_IS_LOCAL(index);
  	if (needLock)
! 		LockRelationForExtension(index, ExclusiveLock);
  
  	buffer = ReadBuffer(index, P_NEW);
  	LockBuffer(buffer, GIN_EXCLUSIVE);
--- 183,193 ----
  	/* Must extend the file */
  	needLock = !RELATION_IS_LOCAL(index);
  	if (needLock)
! 		if (!LockRelationForExtension(index, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on index \"%s\"",
! 					RelationGetRelationName(index))));
  
  	buffer = ReadBuffer(index, P_NEW);
  	LockBuffer(buffer, GIN_EXCLUSIVE);
diff -dcrpN pgsql.orig/src/backend/access/gin/ginvacuum.c pgsql.5/src/backend/access/gin/ginvacuum.c
*** pgsql.orig/src/backend/access/gin/ginvacuum.c	2010-01-03 12:54:01.000000000 +0100
--- pgsql.5/src/backend/access/gin/ginvacuum.c	2010-01-11 22:01:48.000000000 +0100
*************** ginvacuumcleanup(PG_FUNCTION_ARGS)
*** 754,760 ****
  		needLock = !RELATION_IS_LOCAL(index);
  
  	if (needLock)
! 		LockRelationForExtension(index, ExclusiveLock);
  	npages = RelationGetNumberOfBlocks(index);
  	if (needLock)
  		UnlockRelationForExtension(index, ExclusiveLock);
--- 754,764 ----
  		needLock = !RELATION_IS_LOCAL(index);
  
  	if (needLock)
! 		if (!LockRelationForExtension(index, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on index \"%s\"",
! 					RelationGetRelationName(index))));
  	npages = RelationGetNumberOfBlocks(index);
  	if (needLock)
  		UnlockRelationForExtension(index, ExclusiveLock);
*************** ginvacuumcleanup(PG_FUNCTION_ARGS)
*** 800,806 ****
  	stats->pages_free = totFreePages;
  
  	if (needLock)
! 		LockRelationForExtension(index, ExclusiveLock);
  	stats->num_pages = RelationGetNumberOfBlocks(index);
  	if (needLock)
  		UnlockRelationForExtension(index, ExclusiveLock);
--- 804,814 ----
  	stats->pages_free = totFreePages;
  
  	if (needLock)
! 		if (!LockRelationForExtension(index, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on index \"%s\"",
! 					RelationGetRelationName(index))));
  	stats->num_pages = RelationGetNumberOfBlocks(index);
  	if (needLock)
  		UnlockRelationForExtension(index, ExclusiveLock);
diff -dcrpN pgsql.orig/src/backend/access/gist/gistutil.c pgsql.5/src/backend/access/gist/gistutil.c
*** pgsql.orig/src/backend/access/gist/gistutil.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/gist/gistutil.c	2010-01-11 22:01:48.000000000 +0100
*************** gistNewBuffer(Relation r)
*** 653,659 ****
  	needLock = !RELATION_IS_LOCAL(r);
  
  	if (needLock)
! 		LockRelationForExtension(r, ExclusiveLock);
  
  	buffer = ReadBuffer(r, P_NEW);
  	LockBuffer(buffer, GIST_EXCLUSIVE);
--- 653,663 ----
  	needLock = !RELATION_IS_LOCAL(r);
  
  	if (needLock)
! 		if (!LockRelationForExtension(r, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					RelationGetRelationName(r))));
  
  	buffer = ReadBuffer(r, P_NEW);
  	LockBuffer(buffer, GIST_EXCLUSIVE);
diff -dcrpN pgsql.orig/src/backend/access/gist/gistvacuum.c pgsql.5/src/backend/access/gist/gistvacuum.c
*** pgsql.orig/src/backend/access/gist/gistvacuum.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/gist/gistvacuum.c	2010-01-11 22:01:48.000000000 +0100
*************** gistvacuumcleanup(PG_FUNCTION_ARGS)
*** 577,583 ****
  
  	/* try to find deleted pages */
  	if (needLock)
! 		LockRelationForExtension(rel, ExclusiveLock);
  	npages = RelationGetNumberOfBlocks(rel);
  	if (needLock)
  		UnlockRelationForExtension(rel, ExclusiveLock);
--- 577,587 ----
  
  	/* try to find deleted pages */
  	if (needLock)
! 		if (!LockRelationForExtension(rel, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					RelationGetRelationName(rel))));
  	npages = RelationGetNumberOfBlocks(rel);
  	if (needLock)
  		UnlockRelationForExtension(rel, ExclusiveLock);
*************** gistvacuumcleanup(PG_FUNCTION_ARGS)
*** 620,626 ****
  	/* return statistics */
  	stats->std.pages_free = totFreePages;
  	if (needLock)
! 		LockRelationForExtension(rel, ExclusiveLock);
  	stats->std.num_pages = RelationGetNumberOfBlocks(rel);
  	if (needLock)
  		UnlockRelationForExtension(rel, ExclusiveLock);
--- 624,634 ----
  	/* return statistics */
  	stats->std.pages_free = totFreePages;
  	if (needLock)
! 		if (!LockRelationForExtension(rel, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					RelationGetRelationName(rel))));
  	stats->std.num_pages = RelationGetNumberOfBlocks(rel);
  	if (needLock)
  		UnlockRelationForExtension(rel, ExclusiveLock);
diff -dcrpN pgsql.orig/src/backend/access/hash/hashpage.c pgsql.5/src/backend/access/hash/hashpage.c
*** pgsql.orig/src/backend/access/hash/hashpage.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/hash/hashpage.c	2010-01-11 22:01:48.000000000 +0100
*************** void
*** 70,76 ****
  _hash_getlock(Relation rel, BlockNumber whichlock, int access)
  {
  	if (USELOCKING(rel))
! 		LockPage(rel, whichlock, access);
  }
  
  /*
--- 70,80 ----
  _hash_getlock(Relation rel, BlockNumber whichlock, int access)
  {
  	if (USELOCKING(rel))
! 		if (!LockPage(rel, whichlock, access))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on page %u of relation \"%s\"",
! 					whichlock, RelationGetRelationName(rel))));
  }
  
  /*
diff -dcrpN pgsql.orig/src/backend/access/heap/heapam.c pgsql.5/src/backend/access/heap/heapam.c
*** pgsql.orig/src/backend/access/heap/heapam.c	2010-01-10 15:49:30.000000000 +0100
--- pgsql.5/src/backend/access/heap/heapam.c	2010-01-11 22:01:48.000000000 +0100
*************** relation_open(Oid relationId, LOCKMODE l
*** 896,902 ****
  
  	/* Get the lock before trying to open the relcache entry */
  	if (lockmode != NoLock)
! 		LockRelationOid(relationId, lockmode);
  
  	/* The relcache does all the real work... */
  	r = RelationIdGetRelation(relationId);
--- 896,918 ----
  
  	/* Get the lock before trying to open the relcache entry */
  	if (lockmode != NoLock)
! 	{
! 		if (!LockRelationOid(relationId, lockmode))
! 		{
! 			char	   *relname = get_rel_name(relationId);
! 
! 			if (relname)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 							relname)));
! 			else
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation with OID %u",
! 							relationId)));
! 		}
! 	}
  
  	/* The relcache does all the real work... */
  	r = RelationIdGetRelation(relationId);
*************** try_relation_open(Oid relationId, LOCKMO
*** 929,935 ****
  
  	/* Get the lock first */
  	if (lockmode != NoLock)
! 		LockRelationOid(relationId, lockmode);
  
  	/*
  	 * Now that we have the lock, probe to see if the relation really exists
--- 945,965 ----
  
  	/* Get the lock first */
  	if (lockmode != NoLock)
! 		if (!LockRelationOid(relationId, lockmode))
! 		{
! 			char	   *relname = get_rel_name(relationId);
! 
! 			if (relname)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 							relname)));
! 			else
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation with OID %u",
! 							relationId)));
! 		}
  
  	/*
  	 * Now that we have the lock, probe to see if the relation really exists
*************** l1:
*** 2106,2112 ****
  		 */
  		if (!have_tuple_lock)
  		{
! 			LockTuple(relation, &(tp.t_self), ExclusiveLock);
  			have_tuple_lock = true;
  		}
  
--- 2136,2146 ----
  		 */
  		if (!have_tuple_lock)
  		{
! 			if (!LockTuple(relation, &(tp.t_self), ExclusiveLock))
! 				ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			have_tuple_lock = true;
  		}
  
*************** l1:
*** 2119,2125 ****
  		if (infomask & HEAP_XMAX_IS_MULTI)
  		{
  			/* wait for multixact */
! 			MultiXactIdWait((MultiXactId) xwait);
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
--- 2153,2163 ----
  		if (infomask & HEAP_XMAX_IS_MULTI)
  		{
  			/* wait for multixact */
! 			if (!MultiXactIdWait((MultiXactId) xwait))
! 				ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
*************** l1:
*** 2145,2151 ****
  		else
  		{
  			/* wait for regular transaction to end */
! 			XactLockTableWait(xwait);
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
--- 2183,2193 ----
  		else
  		{
  			/* wait for regular transaction to end */
! 			if (!XactLockTableWait(xwait))
! 				ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
*************** l2:
*** 2458,2464 ****
  		 */
  		if (!have_tuple_lock)
  		{
! 			LockTuple(relation, &(oldtup.t_self), ExclusiveLock);
  			have_tuple_lock = true;
  		}
  
--- 2500,2510 ----
  		 */
  		if (!have_tuple_lock)
  		{
! 			if (!LockTuple(relation, &(oldtup.t_self), ExclusiveLock))
! 				ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			have_tuple_lock = true;
  		}
  
*************** l2:
*** 2471,2477 ****
  		if (infomask & HEAP_XMAX_IS_MULTI)
  		{
  			/* wait for multixact */
! 			MultiXactIdWait((MultiXactId) xwait);
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
--- 2517,2527 ----
  		if (infomask & HEAP_XMAX_IS_MULTI)
  		{
  			/* wait for multixact */
! 			if (!MultiXactIdWait((MultiXactId) xwait))
! 				ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
*************** l2:
*** 2497,2503 ****
  		else
  		{
  			/* wait for regular transaction to end */
! 			XactLockTableWait(xwait);
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
--- 2547,2557 ----
  		else
  		{
  			/* wait for regular transaction to end */
! 			if (!XactLockTableWait(xwait))
! 				ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on row in relation \"%s\"",
! 						   RelationGetRelationName(relation))));
  			LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
  
  			/*
*************** heap_lock_tuple(Relation relation, HeapT
*** 3080,3085 ****
--- 3134,3140 ----
  	uint16		new_infomask;
  	LOCKMODE	tuple_lock_type;
  	bool		have_tuple_lock = false;
+ 	bool		lock_acquired;
  
  	tuple_lock_type = (mode == LockTupleShared) ? ShareLock : ExclusiveLock;
  
*************** l3:
*** 3144,3158 ****
  		if (!have_tuple_lock)
  		{
  			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;
  		}
  
--- 3199,3212 ----
  		if (!have_tuple_lock)
  		{
  			if (nowait)
! 				lock_acquired = ConditionalLockTuple(relation, tid, tuple_lock_type);
! 			else
! 				lock_acquired = LockTuple(relation, tid, tuple_lock_type);
! 			if (!lock_acquired)
! 				ereport(ERROR,
  							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
  					errmsg("could not obtain lock on row in relation \"%s\"",
  						   RelationGetRelationName(relation))));
  			have_tuple_lock = true;
  		}
  
*************** l3:
*** 3175,3189 ****
  		{
  			/* wait for multixact to end */
  			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);
  
--- 3229,3242 ----
  		{
  			/* wait for multixact to end */
  			if (nowait)
! 				lock_acquired = ConditionalMultiXactIdWait((MultiXactId) xwait);
! 			else
! 				lock_acquired = MultiXactIdWait((MultiXactId) xwait);
! 			if (!lock_acquired)
! 				ereport(ERROR,
  							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
  					errmsg("could not obtain lock on row in relation \"%s\"",
  						   RelationGetRelationName(relation))));
  
  			LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
  
*************** l3:
*** 3210,3224 ****
  		{
  			/* wait for regular transaction to end */
  			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);
  
--- 3263,3276 ----
  		{
  			/* wait for regular transaction to end */
  			if (nowait)
! 				lock_acquired = ConditionalXactLockTableWait(xwait);
! 			else
! 				lock_acquired = XactLockTableWait(xwait);
! 			if (!lock_acquired)
! 				ereport(ERROR,
  							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
  					errmsg("could not obtain lock on row in relation \"%s\"",
  						   RelationGetRelationName(relation))));
  
  			LockBuffer(*buffer, BUFFER_LOCK_EXCLUSIVE);
  
diff -dcrpN pgsql.orig/src/backend/access/heap/hio.c pgsql.5/src/backend/access/heap/hio.c
*** pgsql.orig/src/backend/access/heap/hio.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/heap/hio.c	2010-01-11 22:01:48.000000000 +0100
*************** RelationGetBufferForTuple(Relation relat
*** 317,323 ****
  	needLock = !RELATION_IS_LOCAL(relation);
  
  	if (needLock)
! 		LockRelationForExtension(relation, ExclusiveLock);
  
  	/*
  	 * XXX This does an lseek - rather expensive - but at the moment it is the
--- 317,327 ----
  	needLock = !RELATION_IS_LOCAL(relation);
  
  	if (needLock)
! 		if (!LockRelationForExtension(relation, ExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					RelationGetRelationName(relation))));
  
  	/*
  	 * XXX This does an lseek - rather expensive - but at the moment it is the
diff -dcrpN pgsql.orig/src/backend/access/heap/visibilitymap.c pgsql.5/src/backend/access/heap/visibilitymap.c
*** pgsql.orig/src/backend/access/heap/visibilitymap.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/heap/visibilitymap.c	2010-01-11 22:01:48.000000000 +0100
*************** vm_extend(Relation rel, BlockNumber vm_n
*** 448,454 ****
  	 * Note that another backend might have extended or created the relation
  	 * before we get the lock.
  	 */
! 	LockRelationForExtension(rel, ExclusiveLock);
  
  	/* Create the file first if it doesn't exist */
  	if ((rel->rd_vm_nblocks == 0 || rel->rd_vm_nblocks == InvalidBlockNumber)
--- 448,458 ----
  	 * Note that another backend might have extended or created the relation
  	 * before we get the lock.
  	 */
! 	if (!LockRelationForExtension(rel, ExclusiveLock))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on relation \"%s\"",
! 				RelationGetRelationName(rel))));
  
  	/* Create the file first if it doesn't exist */
  	if ((rel->rd_vm_nblocks == 0 || rel->rd_vm_nblocks == InvalidBlockNumber)
diff -dcrpN pgsql.orig/src/backend/access/nbtree/nbtinsert.c pgsql.5/src/backend/access/nbtree/nbtinsert.c
*** pgsql.orig/src/backend/access/nbtree/nbtinsert.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/nbtree/nbtinsert.c	2010-01-11 22:01:48.000000000 +0100
*************** top:
*** 165,171 ****
  		{
  			/* Have to wait for the other guy ... */
  			_bt_relbuf(rel, buf);
! 			XactLockTableWait(xwait);
  			/* start over... */
  			_bt_freestack(stack);
  			goto top;
--- 165,175 ----
  		{
  			/* Have to wait for the other guy ... */
  			_bt_relbuf(rel, buf);
! 			if (!XactLockTableWait(xwait))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on transaction with ID %u",
! 						xwait)));
  			/* start over... */
  			_bt_freestack(stack);
  			goto top;
diff -dcrpN pgsql.orig/src/backend/access/nbtree/nbtpage.c pgsql.5/src/backend/access/nbtree/nbtpage.c
*** pgsql.orig/src/backend/access/nbtree/nbtpage.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/nbtree/nbtpage.c	2010-01-11 22:01:48.000000000 +0100
*************** _bt_getbuf(Relation rel, BlockNumber blk
*** 537,543 ****
  		needLock = !RELATION_IS_LOCAL(rel);
  
  		if (needLock)
! 			LockRelationForExtension(rel, ExclusiveLock);
  
  		buf = ReadBuffer(rel, P_NEW);
  
--- 537,547 ----
  		needLock = !RELATION_IS_LOCAL(rel);
  
  		if (needLock)
! 			if (!LockRelationForExtension(rel, ExclusiveLock))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 						RelationGetRelationName(rel))));
  
  		buf = ReadBuffer(rel, P_NEW);
  
diff -dcrpN pgsql.orig/src/backend/access/nbtree/nbtree.c pgsql.5/src/backend/access/nbtree/nbtree.c
*** pgsql.orig/src/backend/access/nbtree/nbtree.c	2010-01-03 12:54:02.000000000 +0100
--- pgsql.5/src/backend/access/nbtree/nbtree.c	2010-01-11 22:01:48.000000000 +0100
*************** btvacuumscan(IndexVacuumInfo *info, Inde
*** 671,677 ****
  	{
  		/* Get the current relation length */
  		if (needLock)
! 			LockRelationForExtension(rel, ExclusiveLock);
  		num_pages = RelationGetNumberOfBlocks(rel);
  		if (needLock)
  			UnlockRelationForExtension(rel, ExclusiveLock);
--- 671,681 ----
  	{
  		/* Get the current relation length */
  		if (needLock)
! 			if (!LockRelationForExtension(rel, ExclusiveLock))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 						RelationGetRelationName(rel))));
  		num_pages = RelationGetNumberOfBlocks(rel);
  		if (needLock)
  			UnlockRelationForExtension(rel, ExclusiveLock);
diff -dcrpN pgsql.orig/src/backend/access/transam/multixact.c pgsql.5/src/backend/access/transam/multixact.c
*** pgsql.orig/src/backend/access/transam/multixact.c	2010-01-03 12:54:03.000000000 +0100
--- pgsql.5/src/backend/access/transam/multixact.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 58,63 ****
--- 58,64 ----
  #include "pg_trace.h"
  #include "storage/backendid.h"
  #include "storage/lmgr.h"
+ #include "storage/proc.h"
  #include "storage/procarray.h"
  #include "utils/builtins.h"
  #include "utils/memutils.h"
*************** MultiXactIdSetOldestVisible(void)
*** 583,591 ****
   * But by the time we finish sleeping, someone else may have changed the Xmax
   * of the containing tuple, so the caller needs to iterate on us somehow.
   */
! void
  MultiXactIdWait(MultiXactId multi)
  {
  	TransactionId *members;
  	int			nmembers;
  
--- 584,593 ----
   * But by the time we finish sleeping, someone else may have changed the Xmax
   * of the containing tuple, so the caller needs to iterate on us somehow.
   */
! bool
  MultiXactIdWait(MultiXactId multi)
  {
+ 	bool		result = true;
  	TransactionId *members;
  	int			nmembers;
  
*************** MultiXactIdWait(MultiXactId multi)
*** 602,612 ****
  			debug_elog4(DEBUG2, "MultiXactIdWait: waiting for %d (%u)",
  						i, member);
  			if (!TransactionIdIsCurrentTransactionId(member))
! 				XactLockTableWait(member);
  		}
  
  		pfree(members);
  	}
  }
  
  /*
--- 604,620 ----
  			debug_elog4(DEBUG2, "MultiXactIdWait: waiting for %d (%u)",
  						i, member);
  			if (!TransactionIdIsCurrentTransactionId(member))
! 			{
! 				result = XactLockTableWait(member);
! 				if (!result)
! 					break;
! 			}
  		}
  
  		pfree(members);
  	}
+ 
+ 	return result;
  }
  
  /*
diff -dcrpN pgsql.orig/src/backend/access/transam/xact.c pgsql.5/src/backend/access/transam/xact.c
*** pgsql.orig/src/backend/access/transam/xact.c	2010-01-09 22:01:16.000000000 +0100
--- pgsql.5/src/backend/access/transam/xact.c	2010-01-11 22:01:48.000000000 +0100
*************** AssignTransactionId(TransactionState s)
*** 438,444 ****
  	PG_TRY();
  	{
  		CurrentResourceOwner = s->curTransactionOwner;
! 		XactLockTableInsert(s->transactionId);
  	}
  	PG_CATCH();
  	{
--- 438,448 ----
  	PG_TRY();
  	{
  		CurrentResourceOwner = s->curTransactionOwner;
! 		if (!XactLockTableInsert(s->transactionId))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on transation with ID %u",
! 					s->transactionId)));
  	}
  	PG_CATCH();
  	{
*************** StartTransaction(void)
*** 1616,1622 ****
  	/*
  	 * Lock the virtual transaction id before we announce it in the proc array
  	 */
! 	VirtualXactLockTableInsert(vxid);
  
  	/*
  	 * Advertise it in the proc array.	We assume assignment of
--- 1620,1630 ----
  	/*
  	 * Lock the virtual transaction id before we announce it in the proc array
  	 */
! 	if (!VirtualXactLockTableInsert(vxid))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on virtual transaction with ID %u",
! 				vxid.localTransactionId)));
  
  	/*
  	 * Advertise it in the proc array.	We assume assignment of
diff -dcrpN pgsql.orig/src/backend/catalog/dependency.c pgsql.5/src/backend/catalog/dependency.c
*** pgsql.orig/src/backend/catalog/dependency.c	2010-01-03 12:54:04.000000000 +0100
--- pgsql.5/src/backend/catalog/dependency.c	2010-01-11 22:01:48.000000000 +0100
*************** static void
*** 1166,1176 ****
  AcquireDeletionLock(const ObjectAddress *object)
  {
  	if (object->classId == RelationRelationId)
! 		LockRelationOid(object->objectId, AccessExclusiveLock);
  	else
  		/* assume we should lock the whole object not a sub-object */
! 		LockDatabaseObject(object->classId, object->objectId, 0,
! 						   AccessExclusiveLock);
  }
  
  /*
--- 1166,1188 ----
  AcquireDeletionLock(const ObjectAddress *object)
  {
  	if (object->classId == RelationRelationId)
! 	{
! 		if (!LockRelationOid(object->objectId, AccessExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					get_rel_name(object->objectId))));
! 	}
  	else
+ 	{
  		/* assume we should lock the whole object not a sub-object */
! 		if (!LockDatabaseObject(object->classId, object->objectId, 0,
! 						   AccessExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on class:object: %u:%u",
! 					object->classId, object->objectId)));
! 	}
  }
  
  /*
diff -dcrpN pgsql.orig/src/backend/catalog/index.c pgsql.5/src/backend/catalog/index.c
*** pgsql.orig/src/backend/catalog/index.c	2010-01-06 08:43:22.000000000 +0100
--- pgsql.5/src/backend/catalog/index.c	2010-01-11 22:01:48.000000000 +0100
*************** index_create(Oid heapRelationId,
*** 681,687 ****
  	 * until we commit, this prevents deadlock-risk complaints from lock
  	 * manager in cases such as CLUSTER.
  	 */
! 	LockRelation(indexRelation, AccessExclusiveLock);
  
  	/*
  	 * Fill in fields of the index's pg_class entry that are not set correctly
--- 681,691 ----
  	 * until we commit, this prevents deadlock-risk complaints from lock
  	 * manager in cases such as CLUSTER.
  	 */
! 	if (!LockRelation(indexRelation, AccessExclusiveLock))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on relation \"%s\"",
! 				RelationGetRelationName(indexRelation))));
  
  	/*
  	 * Fill in fields of the index's pg_class entry that are not set correctly
*************** IndexBuildHeapScan(Relation heapRelation
*** 1820,1826 ****
  							TransactionId xwait = HeapTupleHeaderGetXmin(heapTuple->t_data);
  
  							LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
! 							XactLockTableWait(xwait);
  							goto recheck;
  						}
  					}
--- 1824,1834 ----
  							TransactionId xwait = HeapTupleHeaderGetXmin(heapTuple->t_data);
  
  							LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
! 							if (!XactLockTableWait(xwait))
! 								ereport(ERROR,
! 										(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 											errmsg("could not obtain lock on transaction with ID %u",
! 										xwait)));
  							goto recheck;
  						}
  					}
*************** IndexBuildHeapScan(Relation heapRelation
*** 1860,1866 ****
  							TransactionId xwait = HeapTupleHeaderGetXmax(heapTuple->t_data);
  
  							LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
! 							XactLockTableWait(xwait);
  							goto recheck;
  						}
  					}
--- 1868,1878 ----
  							TransactionId xwait = HeapTupleHeaderGetXmax(heapTuple->t_data);
  
  							LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
! 							if (!XactLockTableWait(xwait))
! 								ereport(ERROR,
! 										(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 											errmsg("could not obtain lock on transaction with ID %u",
! 										xwait)));
  							goto recheck;
  						}
  					}
diff -dcrpN pgsql.orig/src/backend/catalog/pg_inherits.c pgsql.5/src/backend/catalog/pg_inherits.c
*** pgsql.orig/src/backend/catalog/pg_inherits.c	2010-01-03 12:54:06.000000000 +0100
--- pgsql.5/src/backend/catalog/pg_inherits.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 28,33 ****
--- 28,34 ----
  #include "parser/parse_type.h"
  #include "storage/lmgr.h"
  #include "utils/fmgroids.h"
+ #include "utils/lsyscache.h"
  #include "utils/syscache.h"
  #include "utils/tqual.h"
  
*************** find_inheritance_children(Oid parentrelI
*** 117,123 ****
  		if (lockmode != NoLock)
  		{
  			/* Get the lock to synchronize against concurrent drop */
! 			LockRelationOid(inhrelid, lockmode);
  
  			/*
  			 * Now that we have the lock, double-check to see if the relation
--- 118,128 ----
  		if (lockmode != NoLock)
  		{
  			/* Get the lock to synchronize against concurrent drop */
! 			if (!LockRelationOid(inhrelid, lockmode))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 						get_rel_name(inhrelid))));
  
  			/*
  			 * Now that we have the lock, double-check to see if the relation
diff -dcrpN pgsql.orig/src/backend/catalog/pg_shdepend.c pgsql.5/src/backend/catalog/pg_shdepend.c
*** pgsql.orig/src/backend/catalog/pg_shdepend.c	2010-01-03 12:54:06.000000000 +0100
--- pgsql.5/src/backend/catalog/pg_shdepend.c	2010-01-11 22:01:48.000000000 +0100
*************** void
*** 968,974 ****
  shdepLockAndCheckObject(Oid classId, Oid objectId)
  {
  	/* AccessShareLock should be OK, since we are not modifying the object */
! 	LockSharedObject(classId, objectId, 0, AccessShareLock);
  
  	switch (classId)
  	{
--- 968,978 ----
  shdepLockAndCheckObject(Oid classId, Oid objectId)
  {
  	/* AccessShareLock should be OK, since we are not modifying the object */
! 	if (!LockSharedObject(classId, objectId, 0, AccessShareLock))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on class:object: %u:%u",
! 				classId, objectId)));
  
  	switch (classId)
  	{
diff -dcrpN pgsql.orig/src/backend/commands/dbcommands.c pgsql.5/src/backend/commands/dbcommands.c
*** pgsql.orig/src/backend/commands/dbcommands.c	2010-01-10 17:32:30.000000000 +0100
--- pgsql.5/src/backend/commands/dbcommands.c	2010-01-11 22:01:48.000000000 +0100
*************** movedb(const char *dbname, const char *t
*** 1013,1020 ****
  	 * lock be released at commit, except that someone could try to move
  	 * relations of the DB back into the old directory while we rmtree() it.)
  	 */
! 	LockSharedObjectForSession(DatabaseRelationId, db_id, 0,
! 							   AccessExclusiveLock);
  
  	/*
  	 * Permission checks
--- 1013,1024 ----
  	 * lock be released at commit, except that someone could try to move
  	 * relations of the DB back into the old directory while we rmtree() it.)
  	 */
! 	if (!LockSharedObjectForSession(DatabaseRelationId, db_id, 0,
! 							   AccessExclusiveLock))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on database \"%s\"",
! 				dbname)));
  
  	/*
  	 * Permission checks
*************** get_db_info(const char *name, LOCKMODE l
*** 1604,1610 ****
  		 * Now that we have a database OID, we can try to lock the DB.
  		 */
  		if (lockmode != NoLock)
! 			LockSharedObject(DatabaseRelationId, dbOid, 0, lockmode);
  
  		/*
  		 * And now, re-fetch the tuple by OID.	If it's still there and still
--- 1608,1618 ----
  		 * Now that we have a database OID, we can try to lock the DB.
  		 */
  		if (lockmode != NoLock)
! 			if (!LockSharedObject(DatabaseRelationId, dbOid, 0, lockmode))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on database \"%s\"",
! 						name)));
  
  		/*
  		 * And now, re-fetch the tuple by OID.	If it's still there and still
diff -dcrpN pgsql.orig/src/backend/commands/indexcmds.c pgsql.5/src/backend/commands/indexcmds.c
*** pgsql.orig/src/backend/commands/indexcmds.c	2010-01-03 12:54:08.000000000 +0100
--- pgsql.5/src/backend/commands/indexcmds.c	2010-01-11 22:01:48.000000000 +0100
*************** DefineIndex(RangeVar *heapRelation,
*** 512,518 ****
  	 * because there are no operations that could change its state while we
  	 * hold lock on the parent table.  This might need to change later.
  	 */
! 	LockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock);
  
  	PopActiveSnapshot();
  	CommitTransactionCommand();
--- 512,522 ----
  	 * because there are no operations that could change its state while we
  	 * hold lock on the parent table.  This might need to change later.
  	 */
! 	if (!LockRelationIdForSession(&heaprelid, ShareUpdateExclusiveLock))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on relation \"%s\"",
! 				get_rel_name(heaprelid.relId))));
  
  	PopActiveSnapshot();
  	CommitTransactionCommand();
*************** DefineIndex(RangeVar *heapRelation,
*** 544,550 ****
  
  	while (VirtualTransactionIdIsValid(*old_lockholders))
  	{
! 		VirtualXactLockTableWait(*old_lockholders);
  		old_lockholders++;
  	}
  
--- 548,558 ----
  
  	while (VirtualTransactionIdIsValid(*old_lockholders))
  	{
! 		if (!VirtualXactLockTableWait(*old_lockholders))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					get_rel_name(heaprelid.relId))));
  		old_lockholders++;
  	}
  
*************** DefineIndex(RangeVar *heapRelation,
*** 631,637 ****
  
  	while (VirtualTransactionIdIsValid(*old_lockholders))
  	{
! 		VirtualXactLockTableWait(*old_lockholders);
  		old_lockholders++;
  	}
  
--- 639,649 ----
  
  	while (VirtualTransactionIdIsValid(*old_lockholders))
  	{
! 		if (!VirtualXactLockTableWait(*old_lockholders))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 					get_rel_name(heaprelid.relId))));
  		old_lockholders++;
  	}
  
*************** DefineIndex(RangeVar *heapRelation,
*** 728,734 ****
  		}
  
  		if (VirtualTransactionIdIsValid(old_snapshots[i]))
! 			VirtualXactLockTableWait(old_snapshots[i]);
  	}
  
  	/*
--- 740,750 ----
  		}
  
  		if (VirtualTransactionIdIsValid(old_snapshots[i]))
! 			if (!VirtualXactLockTableWait(old_snapshots[i]))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 						get_rel_name(heaprelid.relId))));
  	}
  
  	/*
diff -dcrpN pgsql.orig/src/backend/commands/lockcmds.c pgsql.5/src/backend/commands/lockcmds.c
*** pgsql.orig/src/backend/commands/lockcmds.c	2010-01-03 12:54:08.000000000 +0100
--- pgsql.5/src/backend/commands/lockcmds.c	2010-01-11 22:01:48.000000000 +0100
*************** LockTableRecurse(Oid reloid, RangeVar *r
*** 75,80 ****
--- 75,81 ----
  {
  	Relation	rel;
  	AclResult	aclresult;
+ 	bool		result;
  
  	/*
  	 * Acquire the lock.  We must do this first to protect against concurrent
*************** LockTableRecurse(Oid reloid, RangeVar *r
*** 82,107 ****
  	 * won't fail.
  	 */
  	if (nowait)
  	{
! 		if (!ConditionalLockRelationOid(reloid, lockmode))
! 		{
! 			/* try to throw error by name; relation could be deleted... */
! 			char	   *relname = rv ? rv->relname : get_rel_name(reloid);
  
! 			if (relname)
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						 errmsg("could not obtain lock on relation \"%s\"",
! 								relname)));
! 			else
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					  errmsg("could not obtain lock on relation with OID %u",
! 							 reloid)));
! 		}
  	}
- 	else
- 		LockRelationOid(reloid, lockmode);
  
  	/*
  	 * Now that we have the lock, check to see if the relation really exists
--- 83,108 ----
  	 * won't fail.
  	 */
  	if (nowait)
+ 		result = ConditionalLockRelationOid(reloid, lockmode);
+ 	else
+ 		result =  LockRelationOid(reloid, lockmode);
+ 	
+ 	if (!result)
  	{
! 		/* try to throw error by name; relation could be deleted... */
! 		char	   *relname = rv ? rv->relname : get_rel_name(reloid);
  
! 		if (relname)
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					 errmsg("could not obtain lock on relation \"%s\"",
! 							relname)));
! 		else
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 				  errmsg("could not obtain lock on relation with OID %u",
! 						 reloid)));
  	}
  
  	/*
  	 * Now that we have the lock, check to see if the relation really exists
diff -dcrpN pgsql.orig/src/backend/commands/sequence.c pgsql.5/src/backend/commands/sequence.c
*** pgsql.orig/src/backend/commands/sequence.c	2010-01-03 12:54:09.000000000 +0100
--- pgsql.5/src/backend/commands/sequence.c	2010-01-11 22:01:48.000000000 +0100
*************** open_share_lock(SeqTable seq)
*** 876,882 ****
  		PG_TRY();
  		{
  			CurrentResourceOwner = TopTransactionResourceOwner;
! 			LockRelationOid(seq->relid, AccessShareLock);
  		}
  		PG_CATCH();
  		{
--- 876,886 ----
  		PG_TRY();
  		{
  			CurrentResourceOwner = TopTransactionResourceOwner;
! 			if (!LockRelationOid(seq->relid, AccessShareLock))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 						get_rel_name(seq->relid))));
  		}
  		PG_CATCH();
  		{
diff -dcrpN pgsql.orig/src/backend/commands/tablecmds.c pgsql.5/src/backend/commands/tablecmds.c
*** pgsql.orig/src/backend/commands/tablecmds.c	2010-01-06 08:43:23.000000000 +0100
--- pgsql.5/src/backend/commands/tablecmds.c	2010-01-11 22:01:48.000000000 +0100
*************** RemoveRelations(DropStmt *drop)
*** 723,735 ****
  			{
  				Form_pg_index index = (Form_pg_index) GETSTRUCT(tuple);
  
! 				LockRelationOid(index->indrelid, AccessExclusiveLock);
  				ReleaseSysCache(tuple);
  			}
  		}
  
  		/* Get the lock before trying to fetch the syscache entry */
! 		LockRelationOid(relOid, AccessExclusiveLock);
  
  		tuple = SearchSysCache(RELOID,
  							   ObjectIdGetDatum(relOid),
--- 723,743 ----
  			{
  				Form_pg_index index = (Form_pg_index) GETSTRUCT(tuple);
  
! 				if (!LockRelationOid(index->indrelid, AccessExclusiveLock))
! 					ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on relation \"%s\"",
! 							get_rel_name(index->indrelid))));
  				ReleaseSysCache(tuple);
  			}
  		}
  
  		/* Get the lock before trying to fetch the syscache entry */
! 		if (!LockRelationOid(relOid, AccessExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 				errmsg("could not obtain lock on relation \"%s\"",
! 					get_rel_name(relOid))));
  
  		tuple = SearchSysCache(RELOID,
  							   ObjectIdGetDatum(relOid),
diff -dcrpN pgsql.orig/src/backend/commands/user.c pgsql.5/src/backend/commands/user.c
*** pgsql.orig/src/backend/commands/user.c	2010-01-03 12:54:10.000000000 +0100
--- pgsql.5/src/backend/commands/user.c	2010-01-11 22:01:48.000000000 +0100
*************** DropRole(DropRoleStmt *stmt)
*** 900,906 ****
  		 * Lock the role, so nobody can add dependencies to her while we drop
  		 * her.  We keep the lock until the end of transaction.
  		 */
! 		LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock);
  
  		/* Check for pg_shdepend entries depending on this role */
  		if (checkSharedDependencies(AuthIdRelationId, roleid,
--- 900,910 ----
  		 * Lock the role, so nobody can add dependencies to her while we drop
  		 * her.  We keep the lock until the end of transaction.
  		 */
! 		if (!LockSharedObject(AuthIdRelationId, roleid, 0, AccessExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on role \"%s\"",
! 					role)));
  
  		/* Check for pg_shdepend entries depending on this role */
  		if (checkSharedDependencies(AuthIdRelationId, roleid,
diff -dcrpN pgsql.orig/src/backend/commands/vacuum.c pgsql.5/src/backend/commands/vacuum.c
*** pgsql.orig/src/backend/commands/vacuum.c	2010-01-06 08:43:23.000000000 +0100
--- pgsql.5/src/backend/commands/vacuum.c	2010-01-11 22:01:48.000000000 +0100
*************** vacuum_rel(Oid relid, VacuumStmt *vacstm
*** 1159,1165 ****
  	 * same process.
  	 */
  	onerelid = onerel->rd_lockInfo.lockRelId;
! 	LockRelationIdForSession(&onerelid, lmode);
  
  	/*
  	 * Remember the relation's TOAST relation for later, if the caller asked
--- 1159,1169 ----
  	 * same process.
  	 */
  	onerelid = onerel->rd_lockInfo.lockRelId;
! 	if (!LockRelationIdForSession(&onerelid, lmode))
! 		ereport(ERROR,
! 				(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 					errmsg("could not obtain lock on relation \"%s\"",
! 				get_rel_name(onerelid.relId))));
  
  	/*
  	 * Remember the relation's TOAST relation for later, if the caller asked
diff -dcrpN pgsql.orig/src/backend/commands/vacuumlazy.c pgsql.5/src/backend/commands/vacuumlazy.c
*** pgsql.orig/src/backend/commands/vacuumlazy.c	2010-01-03 12:54:10.000000000 +0100
--- pgsql.5/src/backend/commands/vacuumlazy.c	2010-01-11 22:01:48.000000000 +0100
*************** lazy_scan_heap(Relation onerel, LVRelSta
*** 449,455 ****
  			 * it's got exclusive lock on the whole relation.
  			 */
  			LockBuffer(buf, BUFFER_LOCK_UNLOCK);
! 			LockRelationForExtension(onerel, ExclusiveLock);
  			UnlockRelationForExtension(onerel, ExclusiveLock);
  			LockBufferForCleanup(buf);
  			if (PageIsNew(page))
--- 449,459 ----
  			 * it's got exclusive lock on the whole relation.
  			 */
  			LockBuffer(buf, BUFFER_LOCK_UNLOCK);
! 			if (!LockRelationForExtension(onerel, ExclusiveLock))
! 				ereport(ERROR,
! 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 							errmsg("could not obtain lock on relation \"%s\"",
! 						RelationGetRelationName(onerel))));
  			UnlockRelationForExtension(onerel, ExclusiveLock);
  			LockBufferForCleanup(buf);
  			if (PageIsNew(page))
diff -dcrpN pgsql.orig/src/backend/executor/execMain.c pgsql.5/src/backend/executor/execMain.c
*** pgsql.orig/src/backend/executor/execMain.c	2010-01-08 14:37:07.000000000 +0100
--- pgsql.5/src/backend/executor/execMain.c	2010-01-11 22:01:48.000000000 +0100
*************** EvalPlanQualFetch(EState *estate, Relati
*** 1493,1499 ****
  			if (TransactionIdIsValid(SnapshotDirty.xmax))
  			{
  				ReleaseBuffer(buffer);
! 				XactLockTableWait(SnapshotDirty.xmax);
  				continue;		/* loop back to repeat heap_fetch */
  			}
  
--- 1493,1500 ----
  			if (TransactionIdIsValid(SnapshotDirty.xmax))
  			{
  				ReleaseBuffer(buffer);
! 				if (!XactLockTableWait(SnapshotDirty.xmax))
! 					elog(ERROR, "could not obtain lock on transaction with OID %u", SnapshotDirty.xmax);
  				continue;		/* loop back to repeat heap_fetch */
  			}
  
diff -dcrpN pgsql.orig/src/backend/port/posix_sema.c pgsql.5/src/backend/port/posix_sema.c
*** pgsql.orig/src/backend/port/posix_sema.c	2010-01-03 12:54:22.000000000 +0100
--- pgsql.5/src/backend/port/posix_sema.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 24,29 ****
--- 24,30 ----
  #include "miscadmin.h"
  #include "storage/ipc.h"
  #include "storage/pg_sema.h"
+ #include "storage/proc.h" /* for LockTimeout */
  
  
  #ifdef USE_NAMED_POSIX_SEMAPHORES
*************** PGSemaphoreTryLock(PGSemaphore sema)
*** 313,315 ****
--- 314,358 ----
  
  	return true;
  }
+ 
+ /*
+  * PGSemaphoreTimedLock
+  *
+  * Lock a semaphore only if able to do so under the lock_timeout
+  */
+ bool
+ PGSemaphoreTimedLock(PGSemaphore sema, bool interruptOK)
+ {
+ 	int		errStatus;
+ 	struct timespec	timeout;
+ 
+ 	/*
+ 	 * See notes in sysv_sema.c's implementation of PGSemaphoreLock. Just as
+ 	 * that code does for semop(), we handle both the case where sem_wait()
+ 	 * returns errno == EINTR after a signal, and the case where it just keeps
+ 	 * waiting.
+ 	 */
+ 	do
+ 	{
+ 		ImmediateInterruptOK = interruptOK;
+ 		CHECK_FOR_INTERRUPTS();
+ 		if (LockTimeout)
+ 		{
+ 			timeout.tv_sec = LockTimeout / 1000;
+ 			timeout.tv_nsec = (LockTimeout % 1000) * 1000000;
+ 			errStatus = sem_timedwait(PG_SEM_REF(sema), &timeout);
+ 		}
+ 		else
+ 			errStatus = sem_wait(PG_SEM_REF(sema));
+ 		ImmediateInterruptOK = false;
+ 	} while (errStatus < 0 && errno == EINTR);
+ 
+ 	if (errStatus < 0)
+ 	{
+ 		if (errno == ETIMEDOUT)
+ 			return false;		/* failed to lock it */
+ 		/* Otherwise we got trouble */
+ 		elog(FATAL, "sem_wait failed: %m");
+ 	}
+ 	return true;
+ }
diff -dcrpN pgsql.orig/src/backend/port/sysv_sema.c pgsql.5/src/backend/port/sysv_sema.c
*** pgsql.orig/src/backend/port/sysv_sema.c	2010-01-03 12:54:22.000000000 +0100
--- pgsql.5/src/backend/port/sysv_sema.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 30,35 ****
--- 30,36 ----
  #include "miscadmin.h"
  #include "storage/ipc.h"
  #include "storage/pg_sema.h"
+ #include "storage/proc.h" /* for LockTimeout */
  
  
  #ifndef HAVE_UNION_SEMUN
*************** PGSemaphoreTryLock(PGSemaphore sema)
*** 497,499 ****
--- 498,589 ----
  
  	return true;
  }
+ 
+ /*
+  * PGSemaphoreTimedLock
+  *
+  * Lock a semaphore only if able to do so under the lock_timeout
+  */
+ bool
+ PGSemaphoreTimedLock(PGSemaphore sema, bool interruptOK)
+ {
+ 	int			errStatus;
+ 	struct sembuf sops;
+ 	struct timespec timeout;
+ 
+ 	sops.sem_op = -1;			/* decrement */
+ 	sops.sem_flg = 0;
+ 	sops.sem_num = sema->semNum;
+ 
+ 	/*
+ 	 * Note: if errStatus is -1 and errno == EINTR then it means we returned
+ 	 * from the operation prematurely because we were sent a signal.  So we
+ 	 * try and lock the semaphore again.
+ 	 *
+ 	 * Each time around the loop, we check for a cancel/die interrupt.      On
+ 	 * some platforms, if such an interrupt comes in while we are waiting, it
+ 	 * will cause the semop() call to exit with errno == EINTR, allowing us to
+ 	 * service the interrupt (if not in a critical section already) during the
+ 	 * next loop iteration.
+ 	 *
+ 	 * Once we acquire the lock, we do NOT check for an interrupt before
+ 	 * returning.  The caller needs to be able to record ownership of the lock
+ 	 * before any interrupt can be accepted.
+ 	 *
+ 	 * There is a window of a few instructions between CHECK_FOR_INTERRUPTS
+ 	 * and entering the semop() call.  If a cancel/die interrupt occurs in
+ 	 * that window, we would fail to notice it until after we acquire the lock
+ 	 * (or get another interrupt to escape the semop()).  We can avoid this
+ 	 * problem by temporarily setting ImmediateInterruptOK to true before we
+ 	 * do CHECK_FOR_INTERRUPTS; then, a die() interrupt in this interval will
+ 	 * execute directly.  However, there is a huge pitfall: there is another
+ 	 * window of a few instructions after the semop() before we are able to
+ 	 * reset ImmediateInterruptOK.  If an interrupt occurs then, we'll lose
+ 	 * control, which means that the lock has been acquired but our caller did
+ 	 * not get a chance to record the fact. Therefore, we only set
+ 	 * ImmediateInterruptOK if the caller tells us it's OK to do so, ie, the
+ 	 * caller does not need to record acquiring the lock.  (This is currently
+ 	 * true for lockmanager locks, since the process that granted us the lock
+ 	 * did all the necessary state updates. It's not true for SysV semaphores
+ 	 * used to implement LW locks or emulate spinlocks --- but the wait time
+ 	 * for such locks should not be very long, anyway.)
+ 	 *
+ 	 * On some platforms, signals marked SA_RESTART (which is most, for us)
+ 	 * will not interrupt the semop(); it will just keep waiting.  Therefore
+ 	 * it's necessary for cancel/die interrupts to be serviced directly by the
+ 	 * signal handler.      On these platforms the behavior is really the same
+ 	 * whether the signal arrives just before the semop() begins, or while it
+ 	 * is waiting.  The loop on EINTR is thus important only for other types
+ 	 * of interrupts.
+ 	 */
+ 	do
+ 	{
+ 		ImmediateInterruptOK = interruptOK;
+ 		CHECK_FOR_INTERRUPTS();
+ 		if (LockTimeout)
+ 		{
+ 			timeout.tv_sec = LockTimeout / 1000;
+ 			timeout.tv_nsec = (LockTimeout % 1000) * 1000000;
+ 			errStatus = semtimedop(sema->semId, &sops, 1, &timeout);
+ 		}
+ 		else
+ 			errStatus = semop(sema->semId, &sops, 1);
+ 		ImmediateInterruptOK = false;
+ 	} while (errStatus < 0 && errno == EINTR);
+ 
+ 	if (errStatus < 0)
+ 	{
+ 		/* Expect EAGAIN or EWOULDBLOCK (platform-dependent) */
+ #ifdef EAGAIN
+ 		if (errno == EAGAIN)
+ 			return false;		/* failed to lock it */
+ #endif
+ #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
+ 		if (errno == EWOULDBLOCK)
+ 			return false;		/* failed to lock it */
+ #endif
+ 		/* Otherwise we got trouble */
+ 		elog(FATAL, "semop(id=%d) failed: %m", sema->semId);
+ 	}
+ 	return true;
+ }
diff -dcrpN pgsql.orig/src/backend/port/win32_sema.c pgsql.5/src/backend/port/win32_sema.c
*** pgsql.orig/src/backend/port/win32_sema.c	2010-01-03 12:54:22.000000000 +0100
--- pgsql.5/src/backend/port/win32_sema.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 16,21 ****
--- 16,22 ----
  #include "miscadmin.h"
  #include "storage/ipc.h"
  #include "storage/pg_sema.h"
+ #include "storage/proc.h" /* for LockTimeout */
  
  static HANDLE *mySemSet;		/* IDs of sema sets acquired so far */
  static int	numSems;			/* number of sema sets acquired so far */
*************** PGSemaphoreTryLock(PGSemaphore sema)
*** 205,207 ****
--- 206,266 ----
  	/* keep compiler quiet */
  	return false;
  }
+ 
+ /*
+  * PGSemaphoreTimedLock
+  *
+  * Lock a semaphore only if able to do so under the lock_timeout
+  * Serve the interrupt if interruptOK is true.
+  */
+ bool
+ PGSemaphoreTimedLock(PGSemaphore sema, bool interruptOK)
+ {
+ 	DWORD		ret;
+ 	HANDLE		wh[2];
+ 
+ 	wh[0] = *sema;
+ 	wh[1] = pgwin32_signal_event;
+ 
+ 	/*
+ 	 * As in other implementations of PGSemaphoreLock, we need to check for
+ 	 * cancel/die interrupts each time through the loop.  But here, there is
+ 	 * no hidden magic about whether the syscall will internally service a
+ 	 * signal --- we do that ourselves.
+ 	 */
+ 	do
+ 	{
+ 		ImmediateInterruptOK = interruptOK;
+ 		CHECK_FOR_INTERRUPTS();
+ 
+ 		errno = 0;
+ 		ret = WaitForMultipleObjectsEx(2, wh, FALSE, LockTimeout ? LockTimeout : INFINITE, TRUE);
+ 
+ 		if (ret == WAIT_OBJECT_0)
+ 		{
+ 			/* We got it! */
+ 			return true;
+ 		}
+ 		else if (ret == WAIT_TIMEOUT)
+ 		{
+ 			/* Can't get it */
+ 			errno = EAGAIN;
+ 			return false;
+ 		}
+ 		else if (ret == WAIT_OBJECT_0 + 1)
+ 		{
+ 			/* Signal event is set - we have a signal to deliver */
+ 			pgwin32_dispatch_queued_signals();
+ 			errno = EINTR;
+ 		}
+ 		else
+ 			/* Otherwise we are in trouble */
+ 			errno = EIDRM;
+ 
+ 		ImmediateInterruptOK = false;
+ 	} while (errno == EINTR);
+ 
+ 	if (errno != 0)
+ 		ereport(FATAL,
+ 				(errmsg("could not lock semaphore: error code %d", (int) GetLastError())));
+ }
diff -dcrpN pgsql.orig/src/backend/storage/lmgr/lmgr.c pgsql.5/src/backend/storage/lmgr/lmgr.c
*** pgsql.orig/src/backend/storage/lmgr/lmgr.c	2010-01-03 12:54:25.000000000 +0100
--- pgsql.5/src/backend/storage/lmgr/lmgr.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 21,26 ****
--- 21,27 ----
  #include "catalog/catalog.h"
  #include "miscadmin.h"
  #include "storage/lmgr.h"
+ #include "storage/proc.h"
  #include "storage/procarray.h"
  #include "utils/inval.h"
  
*************** SetLocktagRelationOid(LOCKTAG *tag, Oid 
*** 68,74 ****
   * Lock a relation given only its OID.	This should generally be used
   * before attempting to open the relation's relcache entry.
   */
! void
  LockRelationOid(Oid relid, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
--- 69,75 ----
   * Lock a relation given only its OID.	This should generally be used
   * before attempting to open the relation's relcache entry.
   */
! bool
  LockRelationOid(Oid relid, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
*************** LockRelationOid(Oid relid, LOCKMODE lock
*** 78,83 ****
--- 79,87 ----
  
  	res = LockAcquire(&tag, lockmode, false, false);
  
+ 	if (res == LOCKACQUIRE_NOT_AVAIL)
+ 		return false;
+ 
  	/*
  	 * Now that we have the lock, check for invalidation messages, so that we
  	 * will update or flush any stale relcache entry before we try to use it.
*************** LockRelationOid(Oid relid, LOCKMODE lock
*** 89,94 ****
--- 93,100 ----
  	 */
  	if (res != LOCKACQUIRE_ALREADY_HELD)
  		AcceptInvalidationMessages();
+ 
+ 	return true;
  }
  
  /*
*************** UnlockRelationOid(Oid relid, LOCKMODE lo
*** 161,167 ****
   * already-open relation.  Never try to do "relation_open(foo, NoLock)"
   * and then lock with this.
   */
! void
  LockRelation(Relation relation, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
--- 167,173 ----
   * already-open relation.  Never try to do "relation_open(foo, NoLock)"
   * and then lock with this.
   */
! bool
  LockRelation(Relation relation, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
*************** LockRelation(Relation relation, LOCKMODE
*** 173,184 ****
--- 179,195 ----
  
  	res = LockAcquire(&tag, lockmode, false, false);
  
+ 	if (res == LOCKACQUIRE_NOT_AVAIL)
+ 		return false;
+ 
  	/*
  	 * Now that we have the lock, check for invalidation messages; see notes
  	 * in LockRelationOid.
  	 */
  	if (res != LOCKACQUIRE_ALREADY_HELD)
  		AcceptInvalidationMessages();
+ 
+ 	return true;
  }
  
  /*
*************** UnlockRelation(Relation relation, LOCKMO
*** 243,256 ****
   * in any transaction that actually uses the rel, to ensure that the
   * relcache entry is up to date.
   */
! void
  LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
  
! 	(void) LockAcquire(&tag, lockmode, true, false);
  }
  
  /*
--- 254,270 ----
   * in any transaction that actually uses the rel, to ensure that the
   * relcache entry is up to date.
   */
! bool
  LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	SET_LOCKTAG_RELATION(tag, relid->dbId, relid->relId);
  
! 	res = LockAcquire(&tag, lockmode, true, false);
! 	
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** UnlockRelationIdForSession(LockRelId *re
*** 276,291 ****
   * We assume the caller is already holding some type of regular lock on
   * the relation, so no AcceptInvalidationMessages call is needed here.
   */
! void
  LockRelationForExtension(Relation relation, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_RELATION_EXTEND(tag,
  								relation->rd_lockInfo.lockRelId.dbId,
  								relation->rd_lockInfo.lockRelId.relId);
  
! 	(void) LockAcquire(&tag, lockmode, false, false);
  }
  
  /*
--- 290,308 ----
   * We assume the caller is already holding some type of regular lock on
   * the relation, so no AcceptInvalidationMessages call is needed here.
   */
! bool
  LockRelationForExtension(Relation relation, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	SET_LOCKTAG_RELATION_EXTEND(tag,
  								relation->rd_lockInfo.lockRelId.dbId,
  								relation->rd_lockInfo.lockRelId.relId);
  
! 	res = LockAcquire(&tag, lockmode, false, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** UnlockRelationForExtension(Relation rela
*** 309,325 ****
   * Obtain a page-level lock.  This is currently used by some index access
   * methods to lock individual index pages.
   */
! void
  LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_PAGE(tag,
  					 relation->rd_lockInfo.lockRelId.dbId,
  					 relation->rd_lockInfo.lockRelId.relId,
  					 blkno);
  
! 	(void) LockAcquire(&tag, lockmode, false, false);
  }
  
  /*
--- 326,345 ----
   * Obtain a page-level lock.  This is currently used by some index access
   * methods to lock individual index pages.
   */
! bool
  LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	SET_LOCKTAG_PAGE(tag,
  					 relation->rd_lockInfo.lockRelId.dbId,
  					 relation->rd_lockInfo.lockRelId.relId,
  					 blkno);
  
! 	res = LockAcquire(&tag, lockmode, false, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** UnlockPage(Relation relation, BlockNumbe
*** 364,373 ****
   * because we can't afford to keep a separate lock in shared memory for every
   * tuple.  See heap_lock_tuple before using this!
   */
! void
  LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_TUPLE(tag,
  					  relation->rd_lockInfo.lockRelId.dbId,
--- 384,394 ----
   * because we can't afford to keep a separate lock in shared memory for every
   * tuple.  See heap_lock_tuple before using this!
   */
! bool
  LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	SET_LOCKTAG_TUPLE(tag,
  					  relation->rd_lockInfo.lockRelId.dbId,
*************** LockTuple(Relation relation, ItemPointer
*** 375,381 ****
  					  ItemPointerGetBlockNumber(tid),
  					  ItemPointerGetOffsetNumber(tid));
  
! 	(void) LockAcquire(&tag, lockmode, false, false);
  }
  
  /*
--- 396,404 ----
  					  ItemPointerGetBlockNumber(tid),
  					  ItemPointerGetOffsetNumber(tid));
  
! 	res = LockAcquire(&tag, lockmode, false, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** UnlockTuple(Relation relation, ItemPoint
*** 422,435 ****
   * this is done when an XID is acquired by a transaction or subtransaction.
   * The lock can then be used to wait for the transaction to finish.
   */
! void
  XactLockTableInsert(TransactionId xid)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_TRANSACTION(tag, xid);
  
! 	(void) LockAcquire(&tag, ExclusiveLock, false, false);
  }
  
  /*
--- 445,461 ----
   * this is done when an XID is acquired by a transaction or subtransaction.
   * The lock can then be used to wait for the transaction to finish.
   */
! bool
  XactLockTableInsert(TransactionId xid)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	SET_LOCKTAG_TRANSACTION(tag, xid);
  
! 	res = LockAcquire(&tag, ExclusiveLock, false, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** XactLockTableDelete(TransactionId xid)
*** 461,467 ****
   * successfully or unsuccessfully.	So we have to check if it's "still running"
   * and if so wait for its parent.
   */
! void
  XactLockTableWait(TransactionId xid)
  {
  	LOCKTAG		tag;
--- 487,493 ----
   * successfully or unsuccessfully.	So we have to check if it's "still running"
   * and if so wait for its parent.
   */
! bool
  XactLockTableWait(TransactionId xid)
  {
  	LOCKTAG		tag;
*************** XactLockTableWait(TransactionId xid)
*** 473,479 ****
  
  		SET_LOCKTAG_TRANSACTION(tag, xid);
  
! 		(void) LockAcquire(&tag, ShareLock, false, false);
  
  		LockRelease(&tag, ShareLock, false);
  
--- 499,506 ----
  
  		SET_LOCKTAG_TRANSACTION(tag, xid);
  
! 		if (LockAcquire(&tag, ShareLock, false, false) == LOCKACQUIRE_NOT_AVAIL)
! 			return false;
  
  		LockRelease(&tag, ShareLock, false);
  
*************** XactLockTableWait(TransactionId xid)
*** 481,486 ****
--- 508,515 ----
  			break;
  		xid = SubTransGetParent(xid);
  	}
+ 
+ 	return true;
  }
  
  /*
*************** ConditionalXactLockTableWait(Transaction
*** 522,537 ****
   * this is done at main transaction start when its VXID is assigned.
   * The lock can then be used to wait for the transaction to finish.
   */
! void
  VirtualXactLockTableInsert(VirtualTransactionId vxid)
  {
  	LOCKTAG		tag;
  
  	Assert(VirtualTransactionIdIsValid(vxid));
  
  	SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
  
! 	(void) LockAcquire(&tag, ExclusiveLock, false, false);
  }
  
  /*
--- 551,569 ----
   * this is done at main transaction start when its VXID is assigned.
   * The lock can then be used to wait for the transaction to finish.
   */
! bool
  VirtualXactLockTableInsert(VirtualTransactionId vxid)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	Assert(VirtualTransactionIdIsValid(vxid));
  
  	SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
  
! 	res = LockAcquire(&tag, ExclusiveLock, false, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** VirtualXactLockTableInsert(VirtualTransa
*** 540,557 ****
   * Waits until the lock on the given VXID is released, which shows that
   * the top-level transaction owning the VXID has ended.
   */
! void
  VirtualXactLockTableWait(VirtualTransactionId vxid)
  {
  	LOCKTAG		tag;
  
  	Assert(VirtualTransactionIdIsValid(vxid));
  
  	SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
  
! 	(void) LockAcquire(&tag, ShareLock, false, false);
  
  	LockRelease(&tag, ShareLock, false);
  }
  
  /*
--- 572,592 ----
   * Waits until the lock on the given VXID is released, which shows that
   * the top-level transaction owning the VXID has ended.
   */
! bool
  VirtualXactLockTableWait(VirtualTransactionId vxid)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	Assert(VirtualTransactionIdIsValid(vxid));
  
  	SET_LOCKTAG_VIRTUALTRANSACTION(tag, vxid);
  
! 	res = LockAcquire(&tag, ShareLock, false, false);
  
  	LockRelease(&tag, ShareLock, false);
+ 
+ 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** ConditionalVirtualXactLockTableWait(Virt
*** 586,596 ****
   * to relations, also, since a lock taken this way will NOT conflict with
   * locks taken via LockRelation and friends.
   */
! void
  LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
  				   LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_OBJECT(tag,
  					   MyDatabaseId,
--- 621,632 ----
   * to relations, also, since a lock taken this way will NOT conflict with
   * locks taken via LockRelation and friends.
   */
! bool
  LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
  				   LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
  
  	SET_LOCKTAG_OBJECT(tag,
  					   MyDatabaseId,
*************** LockDatabaseObject(Oid classid, Oid obji
*** 598,604 ****
  					   objid,
  					   objsubid);
  
! 	(void) LockAcquire(&tag, lockmode, false, false);
  }
  
  /*
--- 634,642 ----
  					   objid,
  					   objsubid);
  
! 	res = LockAcquire(&tag, lockmode, false, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** UnlockDatabaseObject(Oid classid, Oid ob
*** 624,630 ****
   *
   * Obtain a lock on a shared-across-databases object.
   */
! void
  LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
  				 LOCKMODE lockmode)
  {
--- 662,668 ----
   *
   * Obtain a lock on a shared-across-databases object.
   */
! bool
  LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
  				 LOCKMODE lockmode)
  {
*************** LockSharedObject(Oid classid, Oid objid,
*** 636,645 ****
  					   objid,
  					   objsubid);
  
! 	(void) LockAcquire(&tag, lockmode, false, false);
  
  	/* Make sure syscaches are up-to-date with any changes we waited for */
  	AcceptInvalidationMessages();
  }
  
  /*
--- 674,686 ----
  					   objid,
  					   objsubid);
  
! 	if (LockAcquire(&tag, lockmode, false, false) == LOCKACQUIRE_NOT_AVAIL)
! 		return false;
  
  	/* Make sure syscaches are up-to-date with any changes we waited for */
  	AcceptInvalidationMessages();
+ 
+ 	return true;
  }
  
  /*
*************** UnlockSharedObject(Oid classid, Oid obji
*** 666,676 ****
   * Obtain a session-level lock on a shared-across-databases object.
   * See LockRelationIdForSession for notes about session-level locks.
   */
! void
  LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
  						   LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
  
  	SET_LOCKTAG_OBJECT(tag,
  					   InvalidOid,
--- 707,719 ----
   * Obtain a session-level lock on a shared-across-databases object.
   * See LockRelationIdForSession for notes about session-level locks.
   */
! bool
  LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
  						   LOCKMODE lockmode)
  {
  	LOCKTAG		tag;
+ 	LockAcquireResult res;
+ 	
  
  	SET_LOCKTAG_OBJECT(tag,
  					   InvalidOid,
*************** LockSharedObjectForSession(Oid classid, 
*** 678,684 ****
  					   objid,
  					   objsubid);
  
! 	(void) LockAcquire(&tag, lockmode, true, false);
  }
  
  /*
--- 721,729 ----
  					   objid,
  					   objsubid);
  
! 	res = LockAcquire(&tag, lockmode, true, false);
! 
! 	return (res != LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
diff -dcrpN pgsql.orig/src/backend/storage/lmgr/lock.c pgsql.5/src/backend/storage/lmgr/lock.c
*** pgsql.orig/src/backend/storage/lmgr/lock.c	2010-01-03 12:54:25.000000000 +0100
--- pgsql.5/src/backend/storage/lmgr/lock.c	2010-01-11 22:06:16.000000000 +0100
*************** PROCLOCK_PRINT(const char *where, const 
*** 255,261 ****
  static uint32 proclock_hash(const void *key, Size keysize);
  static void RemoveLocalLock(LOCALLOCK *locallock);
  static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
! static void WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner);
  static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
  			PROCLOCK *proclock, LockMethod lockMethodTable);
  static void CleanUpLock(LOCK *lock, PROCLOCK *proclock,
--- 255,261 ----
  static uint32 proclock_hash(const void *key, Size keysize);
  static void RemoveLocalLock(LOCALLOCK *locallock);
  static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
! static int WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner);
  static bool UnGrantLock(LOCK *lock, LOCKMODE lockmode,
  			PROCLOCK *proclock, LockMethod lockMethodTable);
  static void CleanUpLock(LOCK *lock, PROCLOCK *proclock,
*************** ProcLockHashCode(const PROCLOCKTAG *proc
*** 451,457 ****
   *	dontWait: if true, don't wait to acquire lock
   *
   * Returns one of:
!  *		LOCKACQUIRE_NOT_AVAIL		lock not available, and dontWait=true
   *		LOCKACQUIRE_OK				lock successfully acquired
   *		LOCKACQUIRE_ALREADY_HELD	incremented count for lock already held
   *
--- 451,457 ----
   *	dontWait: if true, don't wait to acquire lock
   *
   * Returns one of:
!  *		LOCKACQUIRE_NOT_AVAIL		lock not available, either dontWait=true or timeout
   *		LOCKACQUIRE_OK				lock successfully acquired
   *		LOCKACQUIRE_ALREADY_HELD	incremented count for lock already held
   *
*************** LockAcquireExtended(const LOCKTAG *lockt
*** 849,855 ****
  										 locktag->locktag_type,
  										 lockmode);
  
! 		WaitOnLock(locallock, owner);
  
  		TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
  										locktag->locktag_field2,
--- 849,855 ----
  										 locktag->locktag_type,
  										 lockmode);
  
! 		status = WaitOnLock(locallock, owner);
  
  		TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
  										locktag->locktag_field2,
*************** LockAcquireExtended(const LOCKTAG *lockt
*** 864,883 ****
  		 * done when the lock was granted to us --- see notes in WaitOnLock.
  		 */
  
! 		/*
! 		 * Check the proclock entry status, in case something in the ipc
! 		 * communication doesn't work correctly.
! 		 */
! 		if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
  		{
! 			PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
! 			LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
! 			/* Should we retry ? */
! 			LWLockRelease(partitionLock);
! 			elog(ERROR, "LockAcquire failed");
  		}
- 		PROCLOCK_PRINT("LockAcquire: granted", proclock);
- 		LOCK_PRINT("LockAcquire: granted", lock, lockmode);
  	}
  
  	LWLockRelease(partitionLock);
--- 864,895 ----
  		 * done when the lock was granted to us --- see notes in WaitOnLock.
  		 */
  
! 		switch (status)
  		{
! 		case STATUS_OK:
! 			/*
! 			 * Check the proclock entry status, in case something in the ipc
! 			 * communication doesn't work correctly.
! 			 */
! 			if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
! 			{
! 				PROCLOCK_PRINT("LockAcquire: INCONSISTENT", proclock);
! 				LOCK_PRINT("LockAcquire: INCONSISTENT", lock, lockmode);
! 				/* Should we retry ? */
! 				LWLockRelease(partitionLock);
! 				elog(ERROR, "LockAcquire failed");
! 			}
! 			PROCLOCK_PRINT("LockAcquire: granted", proclock);
! 			LOCK_PRINT("LockAcquire: granted", lock, lockmode);
! 			break;
! 		case STATUS_WAITING:
! 			PROCLOCK_PRINT("LockAcquire: timed out", proclock);
! 			LOCK_PRINT("LockAcquire: timed out", lock, lockmode);
! 			break;
! 		default:
! 			elog(ERROR, "LockAcquire invalid status");
! 			break;
  		}
  	}
  
  	LWLockRelease(partitionLock);
*************** LockAcquireExtended(const LOCKTAG *lockt
*** 903,909 ****
  							   locktag->locktag_field2);
  	}
  
! 	return LOCKACQUIRE_OK;
  }
  
  /*
--- 915,921 ----
  							   locktag->locktag_field2);
  	}
  
! 	return (status == STATUS_OK ? LOCKACQUIRE_OK : LOCKACQUIRE_NOT_AVAIL);
  }
  
  /*
*************** LockCheckConflicts(LockMethod lockMethod
*** 1005,1010 ****
--- 1017,1023 ----
  void
  GrantLock(LOCK *lock, PROCLOCK *proclock, LOCKMODE lockmode)
  {
+ 	Assert(proclock != NULL);
  	lock->nGranted++;
  	lock->granted[lockmode]++;
  	lock->grantMask |= LOCKBIT_ON(lockmode);
*************** GrantAwaitedLock(void)
*** 1181,1194 ****
   * Caller must have set MyProc->heldLocks to reflect locks already held
   * on the lockable object by this process.
   *
   * The appropriate partition lock must be held at entry.
   */
! static void
  WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
  {
  	LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD(*locallock);
  	LockMethod	lockMethodTable = LockMethods[lockmethodid];
  	char	   *volatile new_status = NULL;
  
  	LOCK_PRINT("WaitOnLock: sleeping on lock",
  			   locallock->lock, locallock->tag.mode);
--- 1194,1213 ----
   * Caller must have set MyProc->heldLocks to reflect locks already held
   * on the lockable object by this process.
   *
+  * Result: returns value of ProcSleep()
+  *	STATUS_OK if we acquired the lock
+  *	STATUS_ERROR if not (deadlock)
+  *	STATUS_WAITING if not (timeout)
+  *
   * The appropriate partition lock must be held at entry.
   */
! static int
  WaitOnLock(LOCALLOCK *locallock, ResourceOwner owner)
  {
  	LOCKMETHODID lockmethodid = LOCALLOCK_LOCKMETHOD(*locallock);
  	LockMethod	lockMethodTable = LockMethods[lockmethodid];
  	char	   *volatile new_status = NULL;
+ 	int		wait_status;
  
  	LOCK_PRINT("WaitOnLock: sleeping on lock",
  			   locallock->lock, locallock->tag.mode);
*************** WaitOnLock(LOCALLOCK *locallock, Resourc
*** 1230,1237 ****
  	 */
  	PG_TRY();
  	{
! 		if (ProcSleep(locallock, lockMethodTable) != STATUS_OK)
  		{
  			/*
  			 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
  			 * now.
--- 1249,1261 ----
  	 */
  	PG_TRY();
  	{
! 		wait_status = ProcSleep(locallock, lockMethodTable);
! 		switch (wait_status)
  		{
+ 		case STATUS_OK:
+ 		case STATUS_WAITING:
+ 			break;
+ 		default:
  			/*
  			 * We failed as a result of a deadlock, see CheckDeadLock(). Quit
  			 * now.
*************** WaitOnLock(LOCALLOCK *locallock, Resourc
*** 1276,1283 ****
  		pfree(new_status);
  	}
  
! 	LOCK_PRINT("WaitOnLock: wakeup on lock",
  			   locallock->lock, locallock->tag.mode);
  }
  
  /*
--- 1300,1313 ----
  		pfree(new_status);
  	}
  
! 	if (wait_status == STATUS_OK)
! 		LOCK_PRINT("WaitOnLock: wakeup on lock",
! 			   locallock->lock, locallock->tag.mode);
! 	else if (wait_status == STATUS_WAITING)
! 		LOCK_PRINT("WaitOnLock: timeout on lock",
  			   locallock->lock, locallock->tag.mode);
+ 
+ 	return wait_status;
  }
  
  /*
diff -dcrpN pgsql.orig/src/backend/storage/lmgr/proc.c pgsql.5/src/backend/storage/lmgr/proc.c
*** pgsql.orig/src/backend/storage/lmgr/proc.c	2010-01-03 12:54:25.000000000 +0100
--- pgsql.5/src/backend/storage/lmgr/proc.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 46,55 ****
  #include "storage/procarray.h"
  #include "storage/spin.h"
  
- 
  /* GUC variables */
  int			DeadlockTimeout = 1000;
  int			StatementTimeout = 0;
  bool		log_lock_waits = false;
  
  /* Pointer to this process's PGPROC struct, if any */
--- 46,55 ----
  #include "storage/procarray.h"
  #include "storage/spin.h"
  
  /* GUC variables */
  int			DeadlockTimeout = 1000;
  int			StatementTimeout = 0;
+ int			LockTimeout = 0;
  bool		log_lock_waits = false;
  
  /* Pointer to this process's PGPROC struct, if any */
*************** ProcQueueInit(PROC_QUEUE *queue)
*** 743,749 ****
   * The lock table's partition lock must be held at entry, and will be held
   * at exit.
   *
!  * Result: STATUS_OK if we acquired the lock, STATUS_ERROR if not (deadlock).
   *
   * ASSUME: that no one will fiddle with the queue until after
   *		we release the partition lock.
--- 743,752 ----
   * The lock table's partition lock must be held at entry, and will be held
   * at exit.
   *
!  * Result:
!  *     STATUS_OK if we acquired the lock
!  *     STATUS_ERROR if not (deadlock)
!  *     STATUS_WAITING if not (timeout)
   *
   * ASSUME: that no one will fiddle with the queue until after
   *		we release the partition lock.
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 765,770 ****
--- 768,774 ----
  	LOCKMASK	myHeldLocks = MyProc->heldLocks;
  	bool		early_deadlock = false;
  	bool		allow_autovacuum_cancel = true;
+ 	bool		timeout_detected = false;
  	int			myWaitStatus;
  	PGPROC	   *proc;
  	int			i;
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 897,903 ****
  		elog(FATAL, "could not set timer for process wakeup");
  
  	/*
! 	 * If someone wakes us between LWLockRelease and PGSemaphoreLock,
  	 * PGSemaphoreLock will not block.	The wakeup is "saved" by the semaphore
  	 * implementation.	While this is normally good, there are cases where a
  	 * saved wakeup might be leftover from a previous operation (for example,
--- 901,907 ----
  		elog(FATAL, "could not set timer for process wakeup");
  
  	/*
! 	 * If someone wakes us between LWLockRelease and PGSemaphoreTimedLock,
  	 * PGSemaphoreLock will not block.	The wakeup is "saved" by the semaphore
  	 * implementation.	While this is normally good, there are cases where a
  	 * saved wakeup might be leftover from a previous operation (for example,
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 915,921 ****
  	 */
  	do
  	{
! 		PGSemaphoreLock(&MyProc->sem, true);
  
  		/*
  		 * waitStatus could change from STATUS_WAITING to something else
--- 919,929 ----
  	 */
  	do
  	{
! 		if (!PGSemaphoreTimedLock(&MyProc->sem, true))
! 		{
! 			timeout_detected = true;
! 			break;
! 		}
  
  		/*
  		 * waitStatus could change from STATUS_WAITING to something else
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1055,1060 ****
--- 1063,1076 ----
  	LWLockAcquire(partitionLock, LW_EXCLUSIVE);
  
  	/*
+ 	 * If we're in timeout, so we're not waiting anymore and
+ 	 * we're not the one that the lock will be granted to.
+ 	 * So remove ourselves from the wait queue.
+ 	 */
+ 	if (timeout_detected)
+ 		RemoveFromWaitQueue(MyProc, hashcode);
+ 
+ 	/*
  	 * We no longer want LockWaitCancel to do anything.
  	 */
  	lockAwaited = NULL;
*************** ProcSleep(LOCALLOCK *locallock, LockMeth
*** 1068,1075 ****
  	/*
  	 * We don't have to do anything else, because the awaker did all the
  	 * necessary update of the lock table and MyProc.
  	 */
! 	return MyProc->waitStatus;
  }
  
  
--- 1084,1093 ----
  	/*
  	 * We don't have to do anything else, because the awaker did all the
  	 * necessary update of the lock table and MyProc.
+ 	 * RemoveFromWaitQueue() have set MyProc->waitStatus = STATUS_ERROR,
+ 	 * we need to distinguish this case.
  	 */
! 	return (timeout_detected ? STATUS_WAITING : MyProc->waitStatus);
  }
  
  
diff -dcrpN pgsql.orig/src/backend/utils/cache/plancache.c pgsql.5/src/backend/utils/cache/plancache.c
*** pgsql.orig/src/backend/utils/cache/plancache.c	2010-01-03 12:54:29.000000000 +0100
--- pgsql.5/src/backend/utils/cache/plancache.c	2010-01-11 22:01:48.000000000 +0100
***************
*** 55,60 ****
--- 55,61 ----
  #include "tcop/tcopprot.h"
  #include "tcop/utility.h"
  #include "utils/inval.h"
+ #include "utils/lsyscache.h"
  #include "utils/memutils.h"
  #include "utils/resowner.h"
  #include "utils/snapmgr.h"
*************** AcquireExecutorLocks(List *stmt_list, bo
*** 714,720 ****
  				lockmode = AccessShareLock;
  
  			if (acquire)
! 				LockRelationOid(rte->relid, lockmode);
  			else
  				UnlockRelationOid(rte->relid, lockmode);
  		}
--- 715,727 ----
  				lockmode = AccessShareLock;
  
  			if (acquire)
! 			{
! 				if (!LockRelationOid(rte->relid, lockmode))
! 					ereport(ERROR,
! 							(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 								errmsg("could not obtain lock on relation \"%s\"",
! 							get_rel_name(rte->relid))));
! 			}
  			else
  				UnlockRelationOid(rte->relid, lockmode);
  		}
*************** ScanQueryForLocks(Query *parsetree, bool
*** 773,779 ****
  				else
  					lockmode = AccessShareLock;
  				if (acquire)
! 					LockRelationOid(rte->relid, lockmode);
  				else
  					UnlockRelationOid(rte->relid, lockmode);
  				break;
--- 780,792 ----
  				else
  					lockmode = AccessShareLock;
  				if (acquire)
! 				{
! 					if (!LockRelationOid(rte->relid, lockmode))
! 						ereport(ERROR,
! 								(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 									errmsg("could not obtain lock on relation \"%s\"",
! 								get_rel_name(rte->relid))));
! 				}
  				else
  					UnlockRelationOid(rte->relid, lockmode);
  				break;
diff -dcrpN pgsql.orig/src/backend/utils/cache/relcache.c pgsql.5/src/backend/utils/cache/relcache.c
*** pgsql.orig/src/backend/utils/cache/relcache.c	2010-01-08 14:37:11.000000000 +0100
--- pgsql.5/src/backend/utils/cache/relcache.c	2010-01-11 22:01:48.000000000 +0100
*************** load_critical_index(Oid indexoid)
*** 2835,2841 ****
  {
  	Relation	ird;
  
! 	LockRelationOid(indexoid, AccessShareLock);
  	ird = RelationBuildDesc(indexoid, NULL);
  	if (ird == NULL)
  		elog(PANIC, "could not open critical system index %u", indexoid);
--- 2835,2842 ----
  {
  	Relation	ird;
  
! 	if (!LockRelationOid(indexoid, AccessShareLock))
! 		elog(PANIC, "could not lock critical system index %u", indexoid);
  	ird = RelationBuildDesc(indexoid, NULL);
  	if (ird == NULL)
  		elog(PANIC, "could not open critical system index %u", indexoid);
diff -dcrpN pgsql.orig/src/backend/utils/init/postinit.c pgsql.5/src/backend/utils/init/postinit.c
*** pgsql.orig/src/backend/utils/init/postinit.c	2010-01-03 12:54:30.000000000 +0100
--- pgsql.5/src/backend/utils/init/postinit.c	2010-01-11 22:01:48.000000000 +0100
*************** InitPostgres(const char *in_dbname, Oid 
*** 624,631 ****
  	 * CREATE DATABASE.
  	 */
  	if (!bootstrap)
! 		LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
! 						 RowExclusiveLock);
  
  	/*
  	 * Recheck pg_database to make sure the target database hasn't gone away.
--- 624,635 ----
  	 * CREATE DATABASE.
  	 */
  	if (!bootstrap)
! 		if (!LockSharedObject(DatabaseRelationId, MyDatabaseId, 0,
! 						 RowExclusiveLock))
! 			ereport(ERROR,
! 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
! 						errmsg("could not obtain lock on database \"%s\"",
! 					in_dbname)));
  
  	/*
  	 * Recheck pg_database to make sure the target database hasn't gone away.
diff -dcrpN pgsql.orig/src/backend/utils/misc/guc.c pgsql.5/src/backend/utils/misc/guc.c
*** pgsql.orig/src/backend/utils/misc/guc.c	2010-01-08 14:37:12.000000000 +0100
--- pgsql.5/src/backend/utils/misc/guc.c	2010-01-11 22:01:48.000000000 +0100
*************** static struct config_int ConfigureNamesI
*** 1584,1589 ****
--- 1584,1599 ----
  	},
  
  	{
+ 		{"lock_timeout", PGC_USERSET, CLIENT_CONN_STATEMENT,
+ 			gettext_noop("Sets the maximum allowed timeout for any lock taken by a statement."),
+ 			gettext_noop("A value of 0 turns off the timeout."),
+ 			GUC_UNIT_MS
+ 		},
+ 		&LockTimeout,
+ 		0, 0, INT_MAX, NULL, NULL
+ 	},
+ 
+ 	{
  		{"vacuum_freeze_min_age", PGC_USERSET, CLIENT_CONN_STATEMENT,
  			gettext_noop("Minimum age at which VACUUM should freeze a table row."),
  			NULL
diff -dcrpN pgsql.orig/src/include/access/multixact.h pgsql.5/src/include/access/multixact.h
*** pgsql.orig/src/include/access/multixact.h	2010-01-03 12:54:36.000000000 +0100
--- pgsql.5/src/include/access/multixact.h	2010-01-11 22:01:48.000000000 +0100
*************** extern MultiXactId MultiXactIdCreate(Tra
*** 46,52 ****
  extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid);
  extern bool MultiXactIdIsRunning(MultiXactId multi);
  extern bool MultiXactIdIsCurrent(MultiXactId multi);
! extern void MultiXactIdWait(MultiXactId multi);
  extern bool ConditionalMultiXactIdWait(MultiXactId multi);
  extern void MultiXactIdSetOldestMember(void);
  extern int	GetMultiXactIdMembers(MultiXactId multi, TransactionId **xids);
--- 46,52 ----
  extern MultiXactId MultiXactIdExpand(MultiXactId multi, TransactionId xid);
  extern bool MultiXactIdIsRunning(MultiXactId multi);
  extern bool MultiXactIdIsCurrent(MultiXactId multi);
! extern bool MultiXactIdWait(MultiXactId multi);
  extern bool ConditionalMultiXactIdWait(MultiXactId multi);
  extern void MultiXactIdSetOldestMember(void);
  extern int	GetMultiXactIdMembers(MultiXactId multi, TransactionId **xids);
diff -dcrpN pgsql.orig/src/include/storage/lmgr.h pgsql.5/src/include/storage/lmgr.h
*** pgsql.orig/src/include/storage/lmgr.h	2010-01-03 12:54:39.000000000 +0100
--- pgsql.5/src/include/storage/lmgr.h	2010-01-11 22:01:48.000000000 +0100
***************
*** 23,79 ****
  extern void RelationInitLockInfo(Relation relation);
  
  /* Lock a relation */
! extern void LockRelationOid(Oid relid, LOCKMODE lockmode);
  extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode);
  extern void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode);
  extern void UnlockRelationOid(Oid relid, LOCKMODE lockmode);
  
! extern void LockRelation(Relation relation, LOCKMODE lockmode);
  extern bool ConditionalLockRelation(Relation relation, LOCKMODE lockmode);
  extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
  
! extern void LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
  extern void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
  
  /* Lock a relation for extension */
! extern void LockRelationForExtension(Relation relation, LOCKMODE lockmode);
  extern void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode);
  
  /* Lock a page (currently only used within indexes) */
! extern void LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
  extern bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
  extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
  
  /* Lock a tuple (see heap_lock_tuple before assuming you understand this) */
! extern void LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
  extern bool ConditionalLockTuple(Relation relation, ItemPointer tid,
  					 LOCKMODE lockmode);
  extern void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
  
  /* Lock an XID (used to wait for a transaction to finish) */
! extern void XactLockTableInsert(TransactionId xid);
  extern void XactLockTableDelete(TransactionId xid);
! extern void XactLockTableWait(TransactionId xid);
  extern bool ConditionalXactLockTableWait(TransactionId xid);
  
  /* Lock a VXID (used to wait for a transaction to finish) */
! extern void VirtualXactLockTableInsert(VirtualTransactionId vxid);
! extern void VirtualXactLockTableWait(VirtualTransactionId vxid);
  extern bool ConditionalVirtualXactLockTableWait(VirtualTransactionId vxid);
  
  /* Lock a general object (other than a relation) of the current database */
! extern void LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
  				   LOCKMODE lockmode);
  extern void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
  					 LOCKMODE lockmode);
  
  /* Lock a shared-across-databases object (other than a relation) */
! extern void LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
  				 LOCKMODE lockmode);
  extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
  				   LOCKMODE lockmode);
  
! extern void LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
  						   LOCKMODE lockmode);
  extern void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
  							 LOCKMODE lockmode);
--- 23,79 ----
  extern void RelationInitLockInfo(Relation relation);
  
  /* Lock a relation */
! extern bool LockRelationOid(Oid relid, LOCKMODE lockmode);
  extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode);
  extern void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode);
  extern void UnlockRelationOid(Oid relid, LOCKMODE lockmode);
  
! extern bool LockRelation(Relation relation, LOCKMODE lockmode);
  extern bool ConditionalLockRelation(Relation relation, LOCKMODE lockmode);
  extern void UnlockRelation(Relation relation, LOCKMODE lockmode);
  
! extern bool LockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
  extern void UnlockRelationIdForSession(LockRelId *relid, LOCKMODE lockmode);
  
  /* Lock a relation for extension */
! extern bool LockRelationForExtension(Relation relation, LOCKMODE lockmode);
  extern void UnlockRelationForExtension(Relation relation, LOCKMODE lockmode);
  
  /* Lock a page (currently only used within indexes) */
! extern bool LockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
  extern bool ConditionalLockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
  extern void UnlockPage(Relation relation, BlockNumber blkno, LOCKMODE lockmode);
  
  /* Lock a tuple (see heap_lock_tuple before assuming you understand this) */
! extern bool LockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
  extern bool ConditionalLockTuple(Relation relation, ItemPointer tid,
  					 LOCKMODE lockmode);
  extern void UnlockTuple(Relation relation, ItemPointer tid, LOCKMODE lockmode);
  
  /* Lock an XID (used to wait for a transaction to finish) */
! extern bool XactLockTableInsert(TransactionId xid);
  extern void XactLockTableDelete(TransactionId xid);
! extern bool XactLockTableWait(TransactionId xid);
  extern bool ConditionalXactLockTableWait(TransactionId xid);
  
  /* Lock a VXID (used to wait for a transaction to finish) */
! extern bool VirtualXactLockTableInsert(VirtualTransactionId vxid);
! extern bool VirtualXactLockTableWait(VirtualTransactionId vxid);
  extern bool ConditionalVirtualXactLockTableWait(VirtualTransactionId vxid);
  
  /* Lock a general object (other than a relation) of the current database */
! extern bool LockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
  				   LOCKMODE lockmode);
  extern void UnlockDatabaseObject(Oid classid, Oid objid, uint16 objsubid,
  					 LOCKMODE lockmode);
  
  /* Lock a shared-across-databases object (other than a relation) */
! extern bool LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
  				 LOCKMODE lockmode);
  extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
  				   LOCKMODE lockmode);
  
! extern bool LockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
  						   LOCKMODE lockmode);
  extern void UnlockSharedObjectForSession(Oid classid, Oid objid, uint16 objsubid,
  							 LOCKMODE lockmode);
diff -dcrpN pgsql.orig/src/include/storage/pg_sema.h pgsql.5/src/include/storage/pg_sema.h
*** pgsql.orig/src/include/storage/pg_sema.h	2010-01-03 12:54:39.000000000 +0100
--- pgsql.5/src/include/storage/pg_sema.h	2010-01-11 22:01:48.000000000 +0100
*************** extern void PGSemaphoreUnlock(PGSemaphor
*** 80,83 ****
--- 80,86 ----
  /* Lock a semaphore only if able to do so without blocking */
  extern bool PGSemaphoreTryLock(PGSemaphore sema);
  
+ /* Lock a semaphore only if able to do so under the lock_timeout */
+ extern bool PGSemaphoreTimedLock(PGSemaphore sema, bool interruptOK);
+ 
  #endif   /* PG_SEMA_H */
diff -dcrpN pgsql.orig/src/include/storage/proc.h pgsql.5/src/include/storage/proc.h
*** pgsql.orig/src/include/storage/proc.h	2010-01-03 12:54:39.000000000 +0100
--- pgsql.5/src/include/storage/proc.h	2010-01-11 22:09:45.000000000 +0100
*************** typedef struct PROC_HDR
*** 161,166 ****
--- 161,167 ----
  /* configurable options */
  extern int	DeadlockTimeout;
  extern int	StatementTimeout;
+ extern int	LockTimeout;
  extern bool log_lock_waits;
  
  extern volatile bool cancel_from_timeout;