? GNUmakefile
? config.log
? config.status
? core.7509
? cscope.files
? cscope.out
? install
? contrib/pgbench/pgbench
? src/Makefile.global
? src/backend/postgres
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/catalog/postgres.shdescription
? src/backend/utils/mb/conversion_procs/conversion_create.sql
? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jis_2004_and_shift_jis_2004/libeuc_jis_2004_and_shift_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jis_2004/libutf8_and_euc_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_shift_jis_2004/libutf8_and_shift_jis_2004.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win/libutf8_and_win.so.0.0
? src/bin/initdb/initdb
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_controldata/pg_controldata
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_dump/pg_restore
? src/bin/pg_resetxlog/pg_resetxlog
? src/bin/psql/psql
? src/bin/scripts/clusterdb
? src/bin/scripts/createdb
? src/bin/scripts/createlang
? src/bin/scripts/createuser
? src/bin/scripts/dropdb
? src/bin/scripts/droplang
? src/bin/scripts/dropuser
? src/bin/scripts/reindexdb
? src/bin/scripts/vacuumdb
? src/include/pg_config.h
? src/include/stamp-h
? src/interfaces/ecpg/compatlib/libecpg_compat.so.2.3
? src/interfaces/ecpg/ecpglib/libecpg.so.5.3
? src/interfaces/ecpg/include/ecpg_config.h
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.2.3
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpq/exports.list
? src/interfaces/libpq/libpq.so.5.1
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/port/pg_config_paths.h
? src/test/regress/libregress.so.0.0
? src/test/regress/pg_regress
? src/test/regress/results
? src/test/regress/testtablespace
? src/test/regress/expected/constraints.out
? src/test/regress/expected/copy.out
? src/test/regress/expected/create_function_1.out
? src/test/regress/expected/create_function_2.out
? src/test/regress/expected/largeobject.out
? src/test/regress/expected/largeobject_1.out
? src/test/regress/expected/misc.out
? src/test/regress/expected/tablespace.out
? src/test/regress/sql/constraints.sql
? src/test/regress/sql/copy.sql
? src/test/regress/sql/create_function_1.sql
? src/test/regress/sql/create_function_2.sql
? src/test/regress/sql/largeobject.sql
? src/test/regress/sql/misc.sql
? src/test/regress/sql/tablespace.sql
? src/timezone/zic
Index: src/backend/commands/analyze.c
===================================================================
RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/analyze.c,v
retrieving revision 1.104
diff -c -r1.104 analyze.c
*** src/backend/commands/analyze.c	6 Apr 2007 04:21:42 -0000	1.104
--- src/backend/commands/analyze.c	11 Apr 2007 07:42:38 -0000
***************
*** 139,144 ****
--- 139,148 ----
  	if (!onerel)
  		return;
  
+ 	/* set the snapshot if not already done so */
+ 	if (ActiveSnapshot == NULL)
+ 		ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
+ 	
  	/*
  	 * Check permissions --- this should match vacuum's check!
  	 */
Index: src/backend/commands/cluster.c
===================================================================
RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/cluster.c,v
retrieving revision 1.159
diff -c -r1.159 cluster.c
*** src/backend/commands/cluster.c	8 Apr 2007 01:26:28 -0000	1.159
--- src/backend/commands/cluster.c	11 Apr 2007 07:42:38 -0000
***************
*** 205,212 ****
  
  			/* Start a new transaction for each relation. */
  			StartTransactionCommand();
! 			/* functions in indexes may want a snapshot set */
! 			ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
  			cluster_rel(rvtc, true);
  			CommitTransactionCommand();
  		}
--- 205,215 ----
  
  			/* Start a new transaction for each relation. */
  			StartTransactionCommand();
! 			/* 
! 			 * functions in indexes may want a snapshot set, but we don't
! 			 * set it until the relation is locked succesfully. This helps
! 			 * us avoid certain deadlocks with CREATE INDEX CONCURRENTLY
! 			 */
  			cluster_rel(rvtc, true);
  			CommitTransactionCommand();
  		}
***************
*** 253,258 ****
--- 256,264 ----
  	if (!OldHeap)
  		return;
  
+ 	if (ActiveSnapshot == NULL)
+ 		ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
+ 
  	/*
  	 * Since we may open a new transaction for each relation, we have to check
  	 * that the relation still is what we think it is.
Index: src/backend/commands/indexcmds.c
===================================================================
RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/indexcmds.c,v
retrieving revision 1.157
diff -c -r1.157 indexcmds.c
*** src/backend/commands/indexcmds.c	13 Mar 2007 00:33:39 -0000	1.157
--- src/backend/commands/indexcmds.c	11 Apr 2007 07:42:38 -0000
***************
*** 512,518 ****
  	 * need not check for that.
  	 */
  	for (ixcnt = 0; ixcnt < snapshot->xcnt; ixcnt++)
! 		XactLockTableWait(snapshot->xip[ixcnt]);
  
  	/* Index can now be marked valid -- update its pg_index entry */
  	pg_index = heap_open(IndexRelationId, RowExclusiveLock);
--- 512,533 ----
  	 * need not check for that.
  	 */
  	for (ixcnt = 0; ixcnt < snapshot->xcnt; ixcnt++)
! 	{
! 		/*
! 		 * Another backend doing VACUUM/ANALYZE/CLUSTER may deadlock with us
! 		 * because we might wait for the other backend to finish while it waits
! 		 * for the lock on the relation. We handle this by waiting for a
! 		 * transaction only if it has already set its serializable
! 		 * snapshot. A backend doing VACUUM/ANALYZE/CLUSTER always grabs lock
! 		 * on the relation first and then set its serializable snapshot.
! 		 *
! 		 * A transaction which hasn't yet set its serializable
! 		 * snapshot can not see any of the tuples that we did not index, so
! 		 * its OK if we don't wait for it.
! 		 */
! 		if (TransactionHasSnapshot(snapshot->xip[ixcnt]))
! 			XactLockTableWait(snapshot->xip[ixcnt]);
! 	}
  
  	/* Index can now be marked valid -- update its pg_index entry */
  	pg_index = heap_open(IndexRelationId, RowExclusiveLock);
Index: src/backend/commands/vacuum.c
===================================================================
RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/commands/vacuum.c,v
retrieving revision 1.349
diff -c -r1.349 vacuum.c
*** src/backend/commands/vacuum.c	14 Mar 2007 18:48:55 -0000	1.349
--- src/backend/commands/vacuum.c	11 Apr 2007 07:42:38 -0000
***************
*** 338,344 ****
  	 *
  	 * For ANALYZE (no VACUUM): if inside a transaction block, we cannot
  	 * start/commit our own transactions.  Also, there's no need to do so if
! 	 * only processing one relation.  For multiple relations when not within a
  	 * transaction block, use own transactions so we can release locks sooner.
  	 */
  	if (vacstmt->vacuum)
--- 338,347 ----
  	 *
  	 * For ANALYZE (no VACUUM): if inside a transaction block, we cannot
  	 * start/commit our own transactions.  Also, there's no need to do so if
! 	 * only processing one relation.  But we still do that because that helps
! 	 * us to set serializable snapshot only after acquiring appropriate lock
! 	 * on the relation. This avoids certain deadlock conditions with CREATE
! 	 * INDEX CONCURRENTLY. For multiple relations when not within a
  	 * transaction block, use own transactions so we can release locks sooner.
  	 */
  	if (vacstmt->vacuum)
***************
*** 348,357 ****
  		Assert(vacstmt->analyze);
  		if (in_outer_xact)
  			use_own_xacts = false;
! 		else if (list_length(relations) > 1)
  			use_own_xacts = true;
- 		else
- 			use_own_xacts = false;
  	}
  
  	/*
--- 351,358 ----
  		Assert(vacstmt->analyze);
  		if (in_outer_xact)
  			use_own_xacts = false;
! 		else 
  			use_own_xacts = true;
  	}
  
  	/*
***************
*** 411,418 ****
  				if (use_own_xacts)
  				{
  					StartTransactionCommand();
! 					/* functions in indexes may want a snapshot set */
! 					ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
  				}
  				else
  					old_context = MemoryContextSwitchTo(anl_context);
--- 412,422 ----
  				if (use_own_xacts)
  				{
  					StartTransactionCommand();
! 					/*
! 					 * functions in indexes may want a snapshot set, but
! 					 * we shall set the snapshot only after acquiring lock on
! 					 * the relation
! 					 */
  				}
  				else
  					old_context = MemoryContextSwitchTo(anl_context);
***************
*** 961,972 ****
  	/* Begin a transaction for vacuuming this relation */
  	StartTransactionCommand();
  
! 	if (vacstmt->full)
! 	{
! 		/* functions in indexes may want a snapshot set */
! 		ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
! 	}
! 	else
  	{
  		/*
  		 * During a lazy VACUUM we do not run any user-supplied functions, and
--- 965,971 ----
  	/* Begin a transaction for vacuuming this relation */
  	StartTransactionCommand();
  
! 	if (!vacstmt->full)
  	{
  		/*
  		 * During a lazy VACUUM we do not run any user-supplied functions, and
***************
*** 1017,1022 ****
--- 1016,1027 ----
  		return;
  	}
  
+ 	if (ActiveSnapshot == NULL)
+ 	{
+ 		/* functions in indexes may want a snapshot set */
+ 		ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
+ 	}
+ 
  	/*
  	 * Check permissions.
  	 *
Index: src/backend/storage/ipc/procarray.c
===================================================================
RCS file: /home/cvs/postgres/cvs/pgsql/src/backend/storage/ipc/procarray.c,v
retrieving revision 1.24
diff -c -r1.24 procarray.c
*** src/backend/storage/ipc/procarray.c	3 Apr 2007 16:34:36 -0000	1.24
--- src/backend/storage/ipc/procarray.c	11 Apr 2007 07:42:38 -0000
***************
*** 1079,1084 ****
--- 1079,1117 ----
  	LWLockRelease(ProcArrayLock);
  }
  
+ /*
+  * Returns true if snapshot is set for the given transaction.
+  */
+ bool
+ TransactionHasSnapshot(TransactionId xid)
+ {
+ 	ProcArrayStruct *arrayP = procArray;
+ 	int			index;
+ 	bool		has_snapshot = false;
+ 	
+ 	LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+ 
+ 	for (index = 0; index < arrayP->numProcs; index++)
+ 	{
+ 		PGPROC	   *proc = arrayP->procs[index];
+ 
+ 		if (proc->pid == 0)
+ 			continue;			/* do not count prepared xacts */
+ 		
+ 		if (proc->xid != xid)
+ 			continue;
+ 
+ 		if (TransactionIdIsValid(proc->xmin))
+ 			has_snapshot = true;
+ 
+ 		break;
+ 	}
+ 
+ 	LWLockRelease(ProcArrayLock);
+ 
+ 	return has_snapshot;
+ }
+ 
  #ifdef XIDCACHE_DEBUG
  
  /*
Index: src/include/storage/procarray.h
===================================================================
RCS file: /home/cvs/postgres/cvs/pgsql/src/include/storage/procarray.h,v
retrieving revision 1.13
diff -c -r1.13 procarray.h
*** src/include/storage/procarray.h	3 Apr 2007 16:34:36 -0000	1.13
--- src/include/storage/procarray.h	11 Apr 2007 07:42:39 -0000
***************
*** 40,44 ****
--- 40,45 ----
  
  extern void XidCacheRemoveRunningXids(TransactionId xid,
  						  int nxids, TransactionId *xids);
+ extern bool	TransactionHasSnapshot(TransactionId xid);
  
  #endif   /* PROCARRAY_H */
