tqual.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 1,080 行 · 第 1/3 页

C
1,080
字号
				return true;	/* deleted after scan started */			else				return false;	/* deleted before scan started */		}		else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))		{			if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))				tuple->t_infomask |= HEAP_XMIN_INVALID;			return false;		}		else			tuple->t_infomask |= HEAP_XMIN_COMMITTED;	}	/*	 * By here, the inserting transaction has committed - have to check	 * when...	 */	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),									 snapshot->xmin))	{		uint32		i;		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),										 snapshot->xmax))			return false;		for (i = 0; i < snapshot->xcnt; i++)		{			if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),									snapshot->xip[i]))				return false;		}	}	if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid or aborted */		return true;	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)		return true;	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))	{		if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))		{			if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)				return true;	/* deleted after scan started */			else				return false;	/* deleted before scan started */		}		if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))		{			if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))				tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */			return true;		}		/* xmax transaction committed */		tuple->t_infomask |= HEAP_XMAX_COMMITTED;	}	/*	 * OK, the deleting transaction committed too ... but when?	 */	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple), snapshot->xmin))	{		uint32		i;		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),										 snapshot->xmax))			return true;		for (i = 0; i < snapshot->xcnt; i++)		{			if (TransactionIdEquals(HeapTupleHeaderGetXmax(tuple), snapshot->xip[i]))				return true;		}	}	return false;}/* * HeapTupleSatisfiesVacuum * *	Determine the status of tuples for VACUUM purposes.  Here, what *	we mainly want to know is if a tuple is potentially visible to *any* *	running transaction.  If so, it can't be removed yet by VACUUM. * * OldestXmin is a cutoff XID (obtained from GetOldestXmin()).	Tuples * 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_ResultHeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin){	/*	 * Has inserting transaction committed?	 *	 * If the inserting transaction aborted, then the tuple was never visible	 * to any other transaction, so we can delete it immediately.	 *	 * NOTE: must check TransactionIdIsInProgress (which looks in PROC array)	 * before TransactionIdDidCommit/TransactionIdDidAbort (which look in	 * pg_clog).  Otherwise we have a race condition where we might decide	 * that a just-committed transaction crashed, because none of the	 * tests succeed.  xact.c is careful to record commit/abort in pg_clog	 * before it unsets MyProc->xid in PROC array.	 */	if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))	{		if (tuple->t_infomask & HEAP_XMIN_INVALID)			return HEAPTUPLE_DEAD;		else if (tuple->t_infomask & HEAP_MOVED_OFF)		{			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);			if (TransactionIdIsCurrentTransactionId(xvac))				return HEAPTUPLE_DELETE_IN_PROGRESS;			if (TransactionIdIsInProgress(xvac))				return HEAPTUPLE_DELETE_IN_PROGRESS;			if (TransactionIdDidCommit(xvac))			{				tuple->t_infomask |= HEAP_XMIN_INVALID;				return HEAPTUPLE_DEAD;			}			tuple->t_infomask |= HEAP_XMIN_COMMITTED;		}		else if (tuple->t_infomask & HEAP_MOVED_IN)		{			TransactionId xvac = HeapTupleHeaderGetXvac(tuple);			if (TransactionIdIsCurrentTransactionId(xvac))				return HEAPTUPLE_INSERT_IN_PROGRESS;			if (TransactionIdIsInProgress(xvac))				return HEAPTUPLE_INSERT_IN_PROGRESS;			if (TransactionIdDidCommit(xvac))				tuple->t_infomask |= HEAP_XMIN_COMMITTED;			else			{				tuple->t_infomask |= HEAP_XMIN_INVALID;				return HEAPTUPLE_DEAD;			}		}		else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))		{			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */				return HEAPTUPLE_INSERT_IN_PROGRESS;			Assert(HeapTupleHeaderGetXmin(tuple) ==				   HeapTupleHeaderGetXmax(tuple));			if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)				return HEAPTUPLE_INSERT_IN_PROGRESS;			/* inserted and then deleted by same xact */			return HEAPTUPLE_DELETE_IN_PROGRESS;		}		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))			tuple->t_infomask |= HEAP_XMIN_COMMITTED;		else		{			/*			 * Not in Progress, Not Committed, so either Aborted or			 * crashed			 */			tuple->t_infomask |= HEAP_XMIN_INVALID;			return HEAPTUPLE_DEAD;		}		/* Should only get here if we set XMIN_COMMITTED */		Assert(tuple->t_infomask & HEAP_XMIN_COMMITTED);	}	/*	 * Okay, the inserter committed, so it was good at some point.	Now	 * what about the deleting transaction?	 */	if (tuple->t_infomask & HEAP_XMAX_INVALID)		return HEAPTUPLE_LIVE;	if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)	{		/*		 * "Deleting" xact really only marked it for update, so the tuple		 * is live in any case.  However, we must make sure that either		 * XMAX_COMMITTED or XMAX_INVALID gets set once the xact is gone;		 * otherwise it is unsafe to recycle CLOG status after vacuuming.		 */		if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))		{			if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))				return HEAPTUPLE_LIVE;			/*			 * We don't really care whether xmax did commit, abort or			 * crash. We know that xmax did mark the tuple for update, but			 * it did not and will never actually update it.			 */			tuple->t_infomask |= HEAP_XMAX_INVALID;		}		return HEAPTUPLE_LIVE;	}	if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))	{		if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))			return HEAPTUPLE_DELETE_IN_PROGRESS;		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))			tuple->t_infomask |= HEAP_XMAX_COMMITTED;		else		{			/*			 * Not in Progress, Not Committed, so either Aborted or			 * crashed			 */			tuple->t_infomask |= HEAP_XMAX_INVALID;			return HEAPTUPLE_LIVE;		}		/* Should only get here if we set XMAX_COMMITTED */		Assert(tuple->t_infomask & HEAP_XMAX_COMMITTED);	}	/*	 * Deleter committed, but check special cases.	 */	if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),							HeapTupleHeaderGetXmax(tuple)))	{		/*		 * inserter also deleted it, so it was never visible to anyone		 * else		 */		return HEAPTUPLE_DEAD;	}	if (!TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin))	{		/* deleting xact is too recent, tuple could still be visible */		return HEAPTUPLE_RECENTLY_DEAD;	}	/* Otherwise, it's dead and removable */	return HEAPTUPLE_DEAD;}/* * SetQuerySnapshot *		Initialize query snapshot for a new query * * The SerializableSnapshot is the first one taken in a transaction. * In serializable mode we just use that one throughout the transaction. * In read-committed mode, we take a new snapshot at the start of each query. */voidSetQuerySnapshot(void){	/* 1st call in xaction? */	if (SerializableSnapshot == NULL)	{		SerializableSnapshot = GetSnapshotData(&SerializableSnapshotData, true);		QuerySnapshot = SerializableSnapshot;		Assert(QuerySnapshot != NULL);		return;	}	if (XactIsoLevel == XACT_SERIALIZABLE)		QuerySnapshot = SerializableSnapshot;	else		QuerySnapshot = GetSnapshotData(&QuerySnapshotData, false);	Assert(QuerySnapshot != NULL);}/* * CopyQuerySnapshot *		Copy the current query snapshot. * * Copying the snapshot is done so that a query is guaranteed to use a * consistent snapshot for its entire execution life, even if the command * counter is incremented or SetQuerySnapshot() is called while it runs * (as could easily happen, due to triggers etc. executing queries). * * The copy is palloc'd in the current memory context. */SnapshotCopyQuerySnapshot(void){	Snapshot	snapshot;	if (QuerySnapshot == NULL)	/* should be set beforehand */		elog(ERROR, "no snapshot has been set");	snapshot = (Snapshot) palloc(sizeof(SnapshotData));	memcpy(snapshot, QuerySnapshot, sizeof(SnapshotData));	if (snapshot->xcnt > 0)	{		snapshot->xip = (TransactionId *)			palloc(snapshot->xcnt * sizeof(TransactionId));		memcpy(snapshot->xip, QuerySnapshot->xip,			   snapshot->xcnt * sizeof(TransactionId));	}	else		snapshot->xip = NULL;	return snapshot;}/* * CopyCurrentSnapshot *		Make a snapshot that is up-to-date as of the current instant, *		and return a copy. * * The copy is palloc'd in the current memory context. */SnapshotCopyCurrentSnapshot(void){	Snapshot	currentSnapshot;	Snapshot	snapshot;	if (QuerySnapshot == NULL)	/* should not be first call in xact */		elog(ERROR, "no snapshot has been set");	/* Update the static struct */	currentSnapshot = GetSnapshotData(&CurrentSnapshotData, false);	currentSnapshot->curcid = GetCurrentCommandId();	/* Make a copy */	snapshot = (Snapshot) palloc(sizeof(SnapshotData));	memcpy(snapshot, currentSnapshot, sizeof(SnapshotData));	if (snapshot->xcnt > 0)	{		snapshot->xip = (TransactionId *)			palloc(snapshot->xcnt * sizeof(TransactionId));		memcpy(snapshot->xip, currentSnapshot->xip,			   snapshot->xcnt * sizeof(TransactionId));	}	else		snapshot->xip = NULL;	return snapshot;}/* * FreeXactSnapshot *		Free snapshot(s) at end of transaction. */voidFreeXactSnapshot(void){	/*	 * We do not free the xip arrays for the snapshot structs;	 * they will be reused soon.  So this is now just a state	 * change to prevent outside callers from accessing the snapshots.	 */	QuerySnapshot = NULL;	SerializableSnapshot = NULL;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?