@ -48,6 +48,7 @@
# include <sys/stat.h>
# include <unistd.h>
# include "access/subtrans.h"
# include "access/transam.h"
# include "access/xact.h"
# include "access/xlog.h"
@ -66,7 +67,6 @@
# include "utils/resowner_private.h"
# include "utils/snapmgr.h"
# include "utils/syscache.h"
# include "utils/tqual.h"
/*
@ -144,6 +144,8 @@ static volatile OldSnapshotControlData *oldSnapshotControl;
static SnapshotData CurrentSnapshotData = { SNAPSHOT_MVCC } ;
static SnapshotData SecondarySnapshotData = { SNAPSHOT_MVCC } ;
SnapshotData CatalogSnapshotData = { SNAPSHOT_MVCC } ;
SnapshotData SnapshotSelfData = { SNAPSHOT_SELF } ;
SnapshotData SnapshotAnyData = { SNAPSHOT_ANY } ;
/* Pointers to valid snapshots */
static Snapshot CurrentSnapshot = NULL ;
@ -2192,3 +2194,125 @@ RestoreTransactionSnapshot(Snapshot snapshot, void *master_pgproc)
{
SetTransactionSnapshot ( snapshot , NULL , InvalidPid , master_pgproc ) ;
}
/*
* XidInMVCCSnapshot
* Is the given XID still - in - progress according to the snapshot ?
*
* Note : GetSnapshotData never stores either top xid or subxids of our own
* backend into a snapshot , so these xids will not be reported as " running "
* by this function . This is OK for current uses , because we always check
* TransactionIdIsCurrentTransactionId first , except when it ' s known the
* XID could not be ours anyway .
*/
bool
XidInMVCCSnapshot ( TransactionId xid , Snapshot snapshot )
{
uint32 i ;
/*
* Make a quick range check to eliminate most XIDs without looking at the
* xip arrays . Note that this is OK even if we convert a subxact XID to
* its parent below , because a subxact with XID < xmin has surely also got
* a parent with XID < xmin , while one with XID > = xmax must belong to a
* parent that was not yet committed at the time of this snapshot .
*/
/* Any xid < xmin is not in-progress */
if ( TransactionIdPrecedes ( xid , snapshot - > xmin ) )
return false ;
/* Any xid >= xmax is in-progress */
if ( TransactionIdFollowsOrEquals ( xid , snapshot - > xmax ) )
return true ;
/*
* Snapshot information is stored slightly differently in snapshots taken
* during recovery .
*/
if ( ! snapshot - > takenDuringRecovery )
{
/*
* If the snapshot contains full subxact data , the fastest way to
* check things is just to compare the given XID against both subxact
* XIDs and top - level XIDs . If the snapshot overflowed , we have to
* use pg_subtrans to convert a subxact XID to its parent XID , but
* then we need only look at top - level XIDs not subxacts .
*/
if ( ! snapshot - > suboverflowed )
{
/* we have full data, so search subxip */
int32 j ;
for ( j = 0 ; j < snapshot - > subxcnt ; j + + )
{
if ( TransactionIdEquals ( xid , snapshot - > subxip [ j ] ) )
return true ;
}
/* not there, fall through to search xip[] */
}
else
{
/*
* Snapshot overflowed , so convert xid to top - level . This is safe
* because we eliminated too - old XIDs above .
*/
xid = SubTransGetTopmostTransaction ( xid ) ;
/*
* If xid was indeed a subxact , we might now have an xid < xmin ,
* so recheck to avoid an array scan . No point in rechecking
* xmax .
*/
if ( TransactionIdPrecedes ( xid , snapshot - > xmin ) )
return false ;
}
for ( i = 0 ; i < snapshot - > xcnt ; i + + )
{
if ( TransactionIdEquals ( xid , snapshot - > xip [ i ] ) )
return true ;
}
}
else
{
int32 j ;
/*
* In recovery we store all xids in the subxact array because it is by
* far the bigger array , and we mostly don ' t know which xids are
* top - level and which are subxacts . The xip array is empty .
*
* We start by searching subtrans , if we overflowed .
*/
if ( snapshot - > suboverflowed )
{
/*
* Snapshot overflowed , so convert xid to top - level . This is safe
* because we eliminated too - old XIDs above .
*/
xid = SubTransGetTopmostTransaction ( xid ) ;
/*
* If xid was indeed a subxact , we might now have an xid < xmin ,
* so recheck to avoid an array scan . No point in rechecking
* xmax .
*/
if ( TransactionIdPrecedes ( xid , snapshot - > xmin ) )
return false ;
}
/*
* We now have either a top - level xid higher than xmin or an
* indeterminate xid . We don ' t know whether it ' s top level or subxact
* but it doesn ' t matter . If it ' s present , the xid is visible .
*/
for ( j = 0 ; j < snapshot - > subxcnt ; j + + )
{
if ( TransactionIdEquals ( xid , snapshot - > subxip [ j ] ) )
return true ;
}
}
return false ;
}