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

📄 xact.c

📁 postgresql8.3.4源码,开源数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
		 *		 * We do not sleep if enableFsync is not turned on, nor if there are		 * fewer than CommitSiblings other backends with active transactions.		 */		if (CommitDelay > 0 && enableFsync &&			CountActiveBackends() >= CommitSiblings)			pg_usleep(CommitDelay);		XLogFlush(XactLastRecEnd);		/*		 * Now we may update the CLOG, if we wrote a COMMIT record above		 */		if (markXidCommitted)		{			TransactionIdCommit(xid);			/* to avoid race conditions, the parent must commit first */			TransactionIdCommitTree(nchildren, children);		}	}	else	{		/*		 * Asynchronous commit case.		 *		 * Report the latest async commit LSN, so that the WAL writer knows to		 * flush this commit.		 */		XLogSetAsyncCommitLSN(XactLastRecEnd);		/*		 * We must not immediately update the CLOG, since we didn't flush the		 * XLOG. Instead, we store the LSN up to which the XLOG must be		 * flushed before the CLOG may be updated.		 */		if (markXidCommitted)		{			TransactionIdAsyncCommit(xid, XactLastRecEnd);			/* to avoid race conditions, the parent must commit first */			TransactionIdAsyncCommitTree(nchildren, children, XactLastRecEnd);		}	}	/*	 * If we entered a commit critical section, leave it now, and let	 * checkpoints proceed.	 */	if (markXidCommitted)	{		MyProc->inCommit = false;		END_CRIT_SECTION();	}	/* Compute latestXid while we have the child XIDs handy */	latestXid = TransactionIdLatest(xid, nchildren, children);	/* Reset XactLastRecEnd until the next transaction writes something */	XactLastRecEnd.xrecoff = 0;cleanup:	/* Clean up local data */	if (rels)		pfree(rels);	return latestXid;}/* *	AtCommit_LocalCache */static voidAtCommit_LocalCache(void){	/*	 * Make catalog changes visible to me for the next command.	 */	CommandEndInvalidationMessages();}/* *	AtCommit_Memory */static voidAtCommit_Memory(void){	/*	 * Now that we're "out" of a transaction, have the system allocate things	 * in the top memory context instead of per-transaction contexts.	 */	MemoryContextSwitchTo(TopMemoryContext);	/*	 * Release all transaction-local memory.	 */	Assert(TopTransactionContext != NULL);	MemoryContextDelete(TopTransactionContext);	TopTransactionContext = NULL;	CurTransactionContext = NULL;	CurrentTransactionState->curTransactionContext = NULL;}/* ---------------------------------------------------------------- *						CommitSubTransaction stuff * ---------------------------------------------------------------- *//* * AtSubCommit_Memory */static voidAtSubCommit_Memory(void){	TransactionState s = CurrentTransactionState;	Assert(s->parent != NULL);	/* Return to parent transaction level's memory context. */	CurTransactionContext = s->parent->curTransactionContext;	MemoryContextSwitchTo(CurTransactionContext);	/*	 * Ordinarily we cannot throw away the child's CurTransactionContext,	 * since the data it contains will be needed at upper commit.  However, if	 * there isn't actually anything in it, we can throw it away.  This avoids	 * a small memory leak in the common case of "trivial" subxacts.	 */	if (MemoryContextIsEmpty(s->curTransactionContext))	{		MemoryContextDelete(s->curTransactionContext);		s->curTransactionContext = NULL;	}}/* * AtSubCommit_childXids * * Pass my own XID and my child XIDs up to my parent as committed children. */static voidAtSubCommit_childXids(void){	TransactionState s = CurrentTransactionState;	int			new_nChildXids;	Assert(s->parent != NULL);	/*	 * The parent childXids array will need to hold my XID and all my	 * childXids, in addition to the XIDs already there.	 */	new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;	/* Allocate or enlarge the parent array if necessary */	if (s->parent->maxChildXids < new_nChildXids)	{		int				new_maxChildXids;		TransactionId  *new_childXids;		/*		 * Make it 2x what's needed right now, to avoid having to enlarge it		 * repeatedly. But we can't go above MaxAllocSize.  (The latter		 * limit is what ensures that we don't need to worry about integer		 * overflow here or in the calculation of new_nChildXids.)		 */		new_maxChildXids = Min(new_nChildXids * 2,							   (int) (MaxAllocSize / sizeof(TransactionId)));		if (new_maxChildXids < new_nChildXids)			ereport(ERROR,					(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),					 errmsg("maximum number of committed subtransactions (%d) exceeded",							(int) (MaxAllocSize / sizeof(TransactionId)))));		/*		 * We keep the child-XID arrays in TopTransactionContext; this avoids		 * setting up child-transaction contexts for what might be just a few		 * bytes of grandchild XIDs.		 */		if (s->parent->childXids == NULL)			new_childXids =				MemoryContextAlloc(TopTransactionContext, 								   new_maxChildXids * sizeof(TransactionId));		else			new_childXids = repalloc(s->parent->childXids, 									 new_maxChildXids * sizeof(TransactionId));		s->parent->childXids  = new_childXids;		s->parent->maxChildXids = new_maxChildXids;	}	/*	 * Copy all my XIDs to parent's array.	 *	 * Note: We rely on the fact that the XID of a child always follows that	 * of its parent.  By copying the XID of this subtransaction before the	 * XIDs of its children, we ensure that the array stays ordered.  Likewise,	 * all XIDs already in the array belong to subtransactions started and	 * subcommitted before us, so their XIDs must precede ours.	 */	s->parent->childXids[s->parent->nChildXids] = s->transactionId;	if (s->nChildXids > 0)		memcpy(&s->parent->childXids[s->parent->nChildXids + 1],			   s->childXids,			   s->nChildXids * sizeof(TransactionId));	s->parent->nChildXids = new_nChildXids;	/* Release child's array to avoid leakage */	if (s->childXids != NULL)		pfree(s->childXids);	/* We must reset these to avoid double-free if fail later in commit */	s->childXids = NULL;	s->nChildXids = 0;	s->maxChildXids = 0;}/* * RecordSubTransactionCommit */static voidRecordSubTransactionCommit(void){	TransactionId xid = GetCurrentTransactionIdIfAny();	/*	 * We do not log the subcommit in XLOG; it doesn't matter until the	 * top-level transaction commits.	 *	 * We must mark the subtransaction subcommitted in the CLOG if it had a	 * valid XID assigned.	If it did not, nobody else will ever know about	 * the existence of this subxact.  We don't have to deal with deletions	 * scheduled for on-commit here, since they'll be reassigned to our parent	 * (who might still abort).	 */	if (TransactionIdIsValid(xid))	{		/* XXX does this really need to be a critical section? */		START_CRIT_SECTION();		/* Record subtransaction subcommit */		TransactionIdSubCommit(xid);		END_CRIT_SECTION();	}}/* ---------------------------------------------------------------- *						AbortTransaction stuff * ---------------------------------------------------------------- *//* *	RecordTransactionAbort * * Returns latest XID among xact and its children, or InvalidTransactionId * if the xact has no XID.	(We compute that here just because it's easier.) */static TransactionIdRecordTransactionAbort(bool isSubXact){	TransactionId xid = GetCurrentTransactionIdIfAny();	TransactionId latestXid;	int			nrels;	RelFileNode *rels;	int			nchildren;	TransactionId *children;	XLogRecData rdata[3];	int			lastrdata = 0;	xl_xact_abort xlrec;	/*	 * If we haven't been assigned an XID, nobody will care whether we aborted	 * or not.	Hence, we're done in that case.  It does not matter if we have	 * rels to delete (note that this routine is not responsible for actually	 * deleting 'em).  We cannot have any child XIDs, either.	 */	if (!TransactionIdIsValid(xid))	{		/* Reset XactLastRecEnd until the next transaction writes something */		if (!isSubXact)			XactLastRecEnd.xrecoff = 0;		return InvalidTransactionId;	}	/*	 * We have a valid XID, so we should write an ABORT record for it.	 *	 * We do not flush XLOG to disk here, since the default assumption after a	 * crash would be that we aborted, anyway.	For the same reason, we don't	 * need to worry about interlocking against checkpoint start.	 */	/*	 * Check that we haven't aborted halfway through RecordTransactionCommit.	 */	if (TransactionIdDidCommit(xid))		elog(PANIC, "cannot abort transaction %u, it was already committed",			 xid);	/* Fetch the data we need for the abort record */	nrels = smgrGetPendingDeletes(false, &rels, NULL);	nchildren = xactGetCommittedChildren(&children);	/* XXX do we really need a critical section here? */	START_CRIT_SECTION();	/* Write the ABORT record */	if (isSubXact)		xlrec.xact_time = GetCurrentTimestamp();	else	{		SetCurrentTransactionStopTimestamp();		xlrec.xact_time = xactStopTimestamp;	}	xlrec.nrels = nrels;	xlrec.nsubxacts = nchildren;	rdata[0].data = (char *) (&xlrec);	rdata[0].len = MinSizeOfXactAbort;	rdata[0].buffer = InvalidBuffer;	/* dump rels to delete */	if (nrels > 0)	{		rdata[0].next = &(rdata[1]);		rdata[1].data = (char *) rels;		rdata[1].len = nrels * sizeof(RelFileNode);		rdata[1].buffer = InvalidBuffer;		lastrdata = 1;	}	/* dump committed child Xids */	if (nchildren > 0)	{		rdata[lastrdata].next = &(rdata[2]);		rdata[2].data = (char *) children;		rdata[2].len = nchildren * sizeof(TransactionId);		rdata[2].buffer = InvalidBuffer;		lastrdata = 2;	}	rdata[lastrdata].next = NULL;	(void) XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);	/*	 * Mark the transaction aborted in clog.  This is not absolutely necessary	 * but we may as well do it while we are here; also, in the subxact case	 * it is helpful because XactLockTableWait makes use of it to avoid	 * waiting for already-aborted subtransactions.  It is OK to do it without	 * having flushed the ABORT record to disk, because in event of a crash	 * we'd be assumed to have aborted anyway.	 *	 * The ordering here isn't critical but it seems best to mark the parent	 * first.  This assures an atomic transition of all the subtransactions to	 * aborted state from the point of view of concurrent	 * TransactionIdDidAbort calls.	 */	TransactionIdAbort(xid);	TransactionIdAbortTree(nchildren, children);	END_CRIT_SECTION();	/* Compute latestXid while we have the child XIDs handy */	latestXid = TransactionIdLatest(xid, nchildren, children);	/*	 * If we're aborting a subtransaction, we can immediately remove failed	 * XIDs from PGPROC's cache of running child XIDs.  We do that here for	 * subxacts, because we already have the child XID array at hand.  For	 * main xacts, the equivalent happens just after this function returns.	 */	if (isSubXact)		XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);	/* Reset XactLastRecEnd until the next transaction writes something */	if (!isSubXact)		XactLastRecEnd.xrecoff = 0;	/* And clean up local data */	if (rels)		pfree(rels);	return latestXid;}/* *	AtAbort_Memory */static voidAtAbort_Memory(void){	/*	 * Switch into TransactionAbortContext, which should have some free space	 * even if nothing else does.  We'll work in this context until we've	 * finished cleaning up.	 *	 * It is barely possible to get here when we've not been able to create	 * TransactionAbortContext yet; if so use TopMemoryContext.	 */	if (TransactionAbortContext != NULL)		MemoryContextSwitchTo(TransactionAbortContext);	else		MemoryContextSwitchTo(TopMemoryContext);}/* * AtSubAbort_Memory */static voidAtSubAbort_Memory(void){	Assert(TransactionAbortContext != NULL);	MemoryContextSwitchTo(TransactionAbortContext);}/* *	AtAbort_ResourceOwner */static voidAtAbort_ResourceOwner(void){	/*	 * Make sure we have a valid ResourceOwner, if possible (else it will be	 * NULL, which is OK)	 */	CurrentResourceOwner = TopTransactionResourceOwner;}/* * AtSubAbort_ResourceOwner */static voidAtSubAbort_ResourceOwner(void){	TransactionState s = CurrentTransactionState;	/* Make sure we have a valid ResourceOwner */	CurrentResourceOwner = s->curTransactionOwner;}/* * AtSubAbort_childXids */static voidAtSubAbort_childXids(void){	TransactionState s = CurrentTransactionState;	/*	 * We keep the child-XID arrays in TopTransactionContext (see	 * AtSubCommit_childXids).	This means we'd better free the array	 * explicitly at abort to avoid leakage.	 */	if (s->childXids != NULL)		pfree(s->childXids);	s->childXids = NULL;	s->nChildXids = 0;	s->maxChildXids = 0;}/* ---------------------------------------------------------------- *						CleanupTransaction stuff * ---------------------------------------------------------------- *//* *	AtCleanup_Memory */

⌨️ 快捷键说明

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