Index: src/backend/commands/vacuum.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/vacuum.c,v
retrieving revision 1.354
diff -c -r1.354 vacuum.c
*** src/backend/commands/vacuum.c	1 Aug 2007 22:45:08 -0000	1.354
--- src/backend/commands/vacuum.c	9 Aug 2007 07:24:41 -0000
***************
*** 1384,1390 ****
  			tuple.t_len = ItemIdGetLength(itemid);
  			ItemPointerSet(&(tuple.t_self), blkno, offnum);
  
! 			switch (HeapTupleSatisfiesVacuum(tuple.t_data, OldestXmin, buf))
  			{
  				case HEAPTUPLE_DEAD:
  					tupgone = true;		/* we can delete the tuple */
--- 1384,1390 ----
  			tuple.t_len = ItemIdGetLength(itemid);
  			ItemPointerSet(&(tuple.t_self), blkno, offnum);
  
! 			switch (HeapTupleSatisfiesVacuumFull(tuple.t_data, OldestXmin, buf))
  			{
  				case HEAPTUPLE_DEAD:
  					tupgone = true;		/* we can delete the tuple */
***************
*** 1998,2004 ****
  						break;
  					}
  					/* must check for DEAD or MOVED_IN tuple, too */
! 					nextTstatus = HeapTupleSatisfiesVacuum(nextTdata,
  														   OldestXmin,
  														   nextBuf);
  					if (nextTstatus == HEAPTUPLE_DEAD ||
--- 1998,2004 ----
  						break;
  					}
  					/* must check for DEAD or MOVED_IN tuple, too */
! 					nextTstatus = HeapTupleSatisfiesVacuumFull(nextTdata,
  														   OldestXmin,
  														   nextBuf);
  					if (nextTstatus == HEAPTUPLE_DEAD ||
Index: src/backend/utils/time/tqual.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/time/tqual.c,v
retrieving revision 1.103
diff -c -r1.103 tqual.c
*** src/backend/utils/time/tqual.c	1 Aug 2007 22:45:09 -0000	1.103
--- src/backend/utils/time/tqual.c	9 Aug 2007 07:24:43 -0000
***************
*** 77,82 ****
--- 77,85 ----
  TransactionId RecentGlobalXmin = InvalidTransactionId;
  
  /* local functions */
+ static HTSV_Result HeapTupleSatisfiesVacuumInternal(HeapTupleHeader tuple, 
+ 						TransactionId OldestXmin, Buffer buffer, bool locked);
+ 
  static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
  
  
***************
*** 1045,1054 ****
   * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
   * still be visible to some open transaction, so we can't remove them,
   * even if we see that the deleting transaction has committed.
   */
  HTSV_Result
! HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
! 						 Buffer buffer)
  {
  	/*
  	 * Has inserting transaction committed?
--- 1048,1060 ----
   * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
   * still be visible to some open transaction, so we can't remove them,
   * even if we see that the deleting transaction has committed.
+  *
+  * If the heap we are checking is exclusively locked, we can skip certain checks
+  * because we know that no transactions that wrote data are still active.
   */
  HTSV_Result
! HeapTupleSatisfiesVacuumInternal(HeapTupleHeader tuple, TransactionId OldestXmin,
! 						 Buffer buffer, bool locked)
  {
  	/*
  	 * Has inserting transaction committed?
***************
*** 1106,1112 ****
  		}
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
  			HeapTupleSetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
! 								 HeapTupleHeaderGetXmin(tuple));
  		else
  		{
  			/*
--- 1112,1119 ----
  		}
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
  			HeapTupleSetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
! 								 (locked ? InvalidTransactionId : 
! 											HeapTupleHeaderGetXmin(tuple)));
  		else
  		{
  			/*
***************
*** 1144,1155 ****
  		{
  			if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
  			{
! 				if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))
  					return HEAPTUPLE_LIVE;
  			}
  			else
  			{
! 				if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
  					return HEAPTUPLE_LIVE;
  			}
  
--- 1151,1162 ----
  		{
  			if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
  			{
! 				if (!locked && MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))
  					return HEAPTUPLE_LIVE;
  			}
  			else
  			{
! 				if (!locked && TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
  					return HEAPTUPLE_LIVE;
  			}
  
***************
*** 1173,1183 ****
  
  	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
  	{
! 		if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
  			return HEAPTUPLE_DELETE_IN_PROGRESS;
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
  			HeapTupleSetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
! 								 HeapTupleHeaderGetXmax(tuple));
  		else
  		{
  			/*
--- 1180,1191 ----
  
  	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
  	{
! 		if (!locked && TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
  			return HEAPTUPLE_DELETE_IN_PROGRESS;
  		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
  			HeapTupleSetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
! 								 (locked ? InvalidTransactionId : 
! 											HeapTupleHeaderGetXmax(tuple)));
  		else
  		{
  			/*
***************
*** 1221,1226 ****
--- 1229,1247 ----
  	return HEAPTUPLE_DEAD;
  }
  
+ HTSV_Result
+ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin,
+ 						 Buffer buffer)
+ {
+ 	return HeapTupleSatisfiesVacuumInternal(tuple, OldestXmin, buffer, false);
+ }
+ 
+ HTSV_Result
+ HeapTupleSatisfiesVacuumFull(HeapTupleHeader tuple, TransactionId OldestXmin,
+ 						 Buffer buffer)
+ {
+ 	return HeapTupleSatisfiesVacuumInternal(tuple, OldestXmin, buffer, true);
+ }
  
  /*
   * GetTransactionSnapshot
Index: src/include/utils/tqual.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/utils/tqual.h,v
retrieving revision 1.67
diff -c -r1.67 tqual.h
*** src/include/utils/tqual.h	25 Jul 2007 12:22:54 -0000	1.67
--- src/include/utils/tqual.h	9 Aug 2007 07:24:45 -0000
***************
*** 144,149 ****
--- 144,151 ----
  						 CommandId curcid, Buffer buffer);
  extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTupleHeader tuple,
  						 TransactionId OldestXmin, Buffer buffer);
+ extern HTSV_Result HeapTupleSatisfiesVacuumFull(HeapTupleHeader tuple,
+ 						 TransactionId OldestXmin, Buffer buffer);
  
  extern Snapshot GetTransactionSnapshot(void);
  extern Snapshot GetLatestSnapshot(void);
