⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tqual.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */				return true;			if (tuple->t_infomask & HEAP_IS_LOCKED)		/* not deleter */				return true;			Assert(!(tuple->t_infomask & HEAP_XMAX_IS_MULTI));			/* deleting subtransaction aborted? */			/* FIXME -- is this correct w.r.t. the cmax of the tuple? */			if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))			{				tuple->t_infomask |= HEAP_XMAX_INVALID;				SetBufferCommitInfoNeedsSave(buffer);				return true;			}			Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));			if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)				return true;	/* deleted after scan started */			else				return false;	/* deleted before scan started */		}		else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))			return false;		else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))		{			tuple->t_infomask |= HEAP_XMIN_COMMITTED;			SetBufferCommitInfoNeedsSave(buffer);		}		else		{			/* it must have aborted or crashed */			tuple->t_infomask |= HEAP_XMIN_INVALID;			SetBufferCommitInfoNeedsSave(buffer);			return false;		}	}	/*	 * By here, the inserting transaction has committed - have to check	 * when...	 *	 * Note that the provided snapshot contains only top-level XIDs, so we	 * have to convert a subxact XID to its parent for comparison. However, we	 * can make first-pass range checks with the given XID, 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.	 */	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),									 snapshot->xmin))	{		TransactionId parentXid;		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),										 snapshot->xmax))			return false;		parentXid = SubTransGetTopmostTransaction(HeapTupleHeaderGetXmin(tuple));		if (TransactionIdFollowsOrEquals(parentXid, snapshot->xmin))		{			uint32		i;			/* no point in checking parentXid against xmax here */			for (i = 0; i < snapshot->xcnt; i++)			{				if (TransactionIdEquals(parentXid, snapshot->xip[i]))					return false;			}		}	}	if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid or aborted */		return true;	if (tuple->t_infomask & HEAP_IS_LOCKED)		return true;	if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)	{		/* MultiXacts are currently only allowed to lock tuples */		Assert(tuple->t_infomask & HEAP_IS_LOCKED);		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 (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))			return true;		if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))		{			/* it must have aborted or crashed */			tuple->t_infomask |= HEAP_XMAX_INVALID;			SetBufferCommitInfoNeedsSave(buffer);			return true;		}		/* xmax transaction committed */		tuple->t_infomask |= HEAP_XMAX_COMMITTED;		SetBufferCommitInfoNeedsSave(buffer);	}	/*	 * OK, the deleting transaction committed too ... but when?	 *	 * See notes for the similar tests on tuple xmin, above.	 */	if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),									 snapshot->xmin))	{		TransactionId parentXid;		if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),										 snapshot->xmax))			return true;		parentXid = SubTransGetTopmostTransaction(HeapTupleHeaderGetXmax(tuple));		if (TransactionIdFollowsOrEquals(parentXid, snapshot->xmin))		{			uint32		i;			/* no point in checking parentXid against xmax here */			for (i = 0; i < snapshot->xcnt; i++)			{				if (TransactionIdEquals(parentXid, snapshot->xip[i]))					return true;			}		}	}/* This is to be used only for disaster recovery and requires serious analysis. */#ifndef MAKE_EXPIRED_TUPLES_VISIBLE	return false;#else	return true;#endif}/* * 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,						 Buffer buffer){	/*	 * 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.	 */	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;				SetBufferCommitInfoNeedsSave(buffer);				return HEAPTUPLE_DEAD;			}			tuple->t_infomask |= HEAP_XMIN_COMMITTED;			SetBufferCommitInfoNeedsSave(buffer);		}		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;				SetBufferCommitInfoNeedsSave(buffer);			}			else			{				tuple->t_infomask |= HEAP_XMIN_INVALID;				SetBufferCommitInfoNeedsSave(buffer);				return HEAPTUPLE_DEAD;			}		}		else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))		{			if (tuple->t_infomask & HEAP_XMAX_INVALID)	/* xid invalid */				return HEAPTUPLE_INSERT_IN_PROGRESS;			if (tuple->t_infomask & HEAP_IS_LOCKED)				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;			SetBufferCommitInfoNeedsSave(buffer);		}		else		{			/*			 * Not in Progress, Not Committed, so either Aborted or crashed			 */			tuple->t_infomask |= HEAP_XMIN_INVALID;			SetBufferCommitInfoNeedsSave(buffer);			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_IS_LOCKED)	{		/*		 * "Deleting" xact really only locked it, 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 (tuple->t_infomask & HEAP_XMAX_IS_MULTI)			{				if (MultiXactIdIsRunning(HeapTupleHeaderGetXmax(tuple)))					return HEAPTUPLE_LIVE;			}			else			{				if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))					return HEAPTUPLE_LIVE;			}			/*			 * We don't really care whether xmax did commit, abort or crash.			 * We know that xmax did lock the tuple, but it did not and will			 * never actually update it.			 */			tuple->t_infomask |= HEAP_XMAX_INVALID;			SetBufferCommitInfoNeedsSave(buffer);		}		return HEAPTUPLE_LIVE;	}	if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)	{		/* MultiXacts are currently only allowed to lock tuples */		Assert(tuple->t_infomask & HEAP_IS_LOCKED);		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;			SetBufferCommitInfoNeedsSave(buffer);		}		else		{			/*			 * Not in Progress, Not Committed, so either Aborted or crashed			 */			tuple->t_infomask |= HEAP_XMAX_INVALID;			SetBufferCommitInfoNeedsSave(buffer);			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.		 * However, we can only remove it early if it's not an updated tuple;		 * else its parent tuple is linking to it via t_ctid, and this tuple		 * mustn't go away before the parent does.		 */		if (!(tuple->t_infomask & HEAP_UPDATED))			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;}/* * GetTransactionSnapshot *		Get the appropriate snapshot for a new query in a transaction. * * 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 each time we are called. * * Note that the return value points at static storage that will be modified * by future calls and by CommandCounterIncrement().  Callers should copy * the result with CopySnapshot() if it is to be used very long. */SnapshotGetTransactionSnapshot(void){	/* First call in transaction? */	if (SerializableSnapshot == NULL)	{		SerializableSnapshot = GetSnapshotData(&SerializableSnapshotData, true);		return SerializableSnapshot;	}	if (IsXactIsoLevelSerializable)		return SerializableSnapshot;	LatestSnapshot = GetSnapshotData(&LatestSnapshotData, false);	return LatestSnapshot;}/* * GetLatestSnapshot *		Get a snapshot that is up-to-date as of the current instant, *		even if we are executing in SERIALIZABLE mode. */SnapshotGetLatestSnapshot(void){	/* Should not be first call in transaction */	if (SerializableSnapshot == NULL)		elog(ERROR, "no snapshot has been set");	LatestSnapshot = GetSnapshotData(&LatestSnapshotData, false);	return LatestSnapshot;}/* * CopySnapshot *		Copy the given snapshot. * * The copy is palloc'd in the current memory context. * * Note that this will not work on "special" snapshots. */SnapshotCopySnapshot(Snapshot snapshot){	Snapshot	newsnap;	/* We allocate any XID array needed in the same palloc block. */	newsnap = (Snapshot) palloc(sizeof(SnapshotData) +								snapshot->xcnt * sizeof(TransactionId));	memcpy(newsnap, snapshot, sizeof(SnapshotData));	if (snapshot->xcnt > 0)	{		newsnap->xip = (TransactionId *) (newsnap + 1);		memcpy(newsnap->xip, snapshot->xip,			   snapshot->xcnt * sizeof(TransactionId));	}	else		newsnap->xip = NULL;	return newsnap;}/* * FreeSnapshot *		Free a snapshot previously copied with CopySnapshot. * * This is currently identical to pfree, but is provided for cleanliness. * * Do *not* apply this to the results of GetTransactionSnapshot or * GetLatestSnapshot. */voidFreeSnapshot(Snapshot snapshot){	pfree(snapshot);}/* * FreeXactSnapshot *		Free snapshot(s) at end of transaction. */voidFreeXactSnapshot(void){	/*	 * We do not free the xip arrays for the static snapshot structs; they	 * will be reused soon. So this is now just a state change to prevent	 * outside callers from accessing the snapshots.	 */	SerializableSnapshot = NULL;	LatestSnapshot = NULL;	ActiveSnapshot = NULL;		/* just for cleanliness */}

⌨️ 快捷键说明

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