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

📄 xact.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 4 页
字号:
	s->state = TRANS_COMMIT;	/*	 * Do pre-commit processing (most of this stuff requires database	 * access, and in fact could still cause an error...)	 */	AtCommit_Portals();	/* handle commit for large objects [ PA, 7/17/98 ] */	/* XXX probably this does not belong here */	lo_commit(true);	/* NOTIFY commit must come before lower-level cleanup */	AtCommit_Notify();	/* Update the flat password file if we changed pg_shadow or pg_group */	AtEOXact_UpdatePasswordFile(true);	/*	 * Here is where we really truly commit.	 */	RecordTransactionCommit();	/*	 * Let others know about no transaction in progress by me. Note that	 * this must be done _before_ releasing locks we hold and _after_	 * RecordTransactionCommit.	 *	 * LWLockAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked by	 * xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot - if	 * xid 2' GetSnapshotData sees xid 1 as running then it must see xid 0	 * as running as well or it will see two tuple versions - one deleted	 * by xid 1 and one inserted by xid 0.	See notes in GetSnapshotData.	 */	if (MyProc != (PGPROC *) NULL)	{		/* Lock SInvalLock because that's what GetSnapshotData uses. */		LWLockAcquire(SInvalLock, LW_EXCLUSIVE);		MyProc->xid = InvalidTransactionId;		MyProc->xmin = InvalidTransactionId;		LWLockRelease(SInvalLock);	}	/*	 * This is all post-commit cleanup.  Note that if an error is raised	 * here, it's too late to abort the transaction.  This should be just	 * noncritical resource releasing.	 *	 * The ordering of operations is not entirely random.  The idea is:	 * release resources visible to other backends (eg, files, buffer	 * pins); then release locks; then release backend-local resources. We	 * want to release locks at the point where any backend waiting for us	 * will see our transaction as being fully cleaned up.	 */	smgrDoPendingDeletes(true);	AtCommit_Cache();	AtEOXact_Buffers(true);	/* smgrcommit already done */	AtCommit_Locks();	CallEOXactCallbacks(true);	AtEOXact_GUC(true);	AtEOXact_SPI();	AtEOXact_gist();	AtEOXact_hash();	AtEOXact_nbtree();	AtEOXact_rtree();	AtEOXact_on_commit_actions(true);	AtEOXact_Namespace(true);	AtEOXact_CatCache(true);	AtEOXact_Files();	pgstat_count_xact_commit();	AtCommit_Memory();	/*	 * done with commit processing, set current transaction state back to	 * default	 */	s->state = TRANS_DEFAULT;	RESUME_INTERRUPTS();}/* *	AbortTransaction */static voidAbortTransaction(void){	TransactionState s = CurrentTransactionState;	/* Prevent cancel/die interrupt while cleaning up */	HOLD_INTERRUPTS();	/*	 * Release any LW locks we might be holding as quickly as possible.	 * (Regular locks, however, must be held till we finish aborting.)	 * Releasing LW locks is critical since we might try to grab them	 * again while cleaning up!	 */	LWLockReleaseAll();	/* Clean up buffer I/O and buffer context locks, too */	AbortBufferIO();	UnlockBuffers();	/*	 * Also clean up any open wait for lock, since the lock manager will	 * choke if we try to wait for another lock before doing this.	 */	LockWaitCancel();	/*	 * check the current transaction state	 */	if (s->state != TRANS_INPROGRESS)		elog(WARNING, "AbortTransaction and not in in-progress state");	/*	 * set the current transaction state information appropriately during	 * the abort processing	 */	s->state = TRANS_ABORT;	/* Make sure we are in a valid memory context */	AtAbort_Memory();	/*	 * Reset user id which might have been changed transiently	 */	SetUserId(GetSessionUserId());	/*	 * do abort processing	 */	DeferredTriggerAbortXact();	AtAbort_Portals();	lo_commit(false);			/* 'false' means it's abort */	AtAbort_Notify();	AtEOXact_UpdatePasswordFile(false);	/* Advertise the fact that we aborted in pg_clog. */	RecordTransactionAbort();	/*	 * Let others know about no transaction in progress by me. Note that	 * this must be done _before_ releasing locks we hold and _after_	 * RecordTransactionAbort.	 */	if (MyProc != (PGPROC *) NULL)	{		/* Lock SInvalLock because that's what GetSnapshotData uses. */		LWLockAcquire(SInvalLock, LW_EXCLUSIVE);		MyProc->xid = InvalidTransactionId;		MyProc->xmin = InvalidTransactionId;		LWLockRelease(SInvalLock);	}	/*	 * Post-abort cleanup.	See notes in CommitTransaction() concerning	 * ordering.	 */	smgrDoPendingDeletes(false);	AtAbort_Cache();	AtEOXact_Buffers(false);	smgrabort();	AtAbort_Locks();	CallEOXactCallbacks(false);	AtEOXact_GUC(false);	AtEOXact_SPI();	AtEOXact_gist();	AtEOXact_hash();	AtEOXact_nbtree();	AtEOXact_rtree();	AtEOXact_on_commit_actions(false);	AtEOXact_Namespace(false);	AtEOXact_CatCache(false);	AtEOXact_Files();	SetReindexProcessing(InvalidOid, InvalidOid);	pgstat_count_xact_rollback();	/*	 * State remains TRANS_ABORT until CleanupTransaction().	 */	RESUME_INTERRUPTS();}/* *	CleanupTransaction */static voidCleanupTransaction(void){	TransactionState s = CurrentTransactionState;	/*	 * State should still be TRANS_ABORT from AbortTransaction().	 */	if (s->state != TRANS_ABORT)		elog(FATAL, "CleanupTransaction and not in abort state");	/*	 * do abort cleanup processing	 */	AtCleanup_Portals();		/* now safe to release portal memory */	AtCleanup_Memory();			/* and transaction memory */	/*	 * done with abort processing, set current transaction state back to	 * default	 */	s->state = TRANS_DEFAULT;}/* *	StartTransactionCommand */voidStartTransactionCommand(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{			/*			 * if we aren't in a transaction block, we just do our usual			 * start transaction.			 */		case TBLOCK_DEFAULT:			StartTransaction();			break;			/*			 * We should never experience this -- if we do it means the			 * BEGIN state was not changed in the previous			 * CommitTransactionCommand().	If we get it, we print a			 * warning and change to the in-progress state.			 */		case TBLOCK_BEGIN:			elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_BEGIN");			s->blockState = TBLOCK_INPROGRESS;			break;			/*			 * This is the case when are somewhere in a transaction block			 * and about to start a new command.  For now we do nothing			 * but someday we may do command-local resource			 * initialization.			 */		case TBLOCK_INPROGRESS:			break;			/*			 * As with BEGIN, we should never experience this if we do it			 * means the END state was not changed in the previous			 * CommitTransactionCommand().	If we get it, we print a			 * warning, commit the transaction, start a new transaction			 * and change to the default state.			 */		case TBLOCK_END:			elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_END");			s->blockState = TBLOCK_DEFAULT;			CommitTransaction();			StartTransaction();			break;			/*			 * Here we are in the middle of a transaction block but one of			 * the commands caused an abort so we do nothing but remain in			 * the abort state.  Eventually we will get to the "END			 * TRANSACTION" which will set things straight.			 */		case TBLOCK_ABORT:			break;			/*			 * This means we somehow aborted and the last call to			 * CommitTransactionCommand() didn't clear the state so we			 * remain in the ENDABORT state and maybe next time we get to			 * CommitTransactionCommand() the state will get reset to			 * default.			 */		case TBLOCK_ENDABORT:			elog(WARNING, "StartTransactionCommand: unexpected TBLOCK_ENDABORT");			break;	}	/*	 * We must switch to TopTransactionContext before returning. This is	 * already done if we called StartTransaction, otherwise not.	 */	Assert(TopTransactionContext != NULL);	MemoryContextSwitchTo(TopTransactionContext);}/* *	CommitTransactionCommand */voidCommitTransactionCommand(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{			/*			 * If we aren't in a transaction block, just do our usual			 * transaction commit.			 */		case TBLOCK_DEFAULT:			CommitTransaction();			break;			/*			 * This is the case right after we get a "BEGIN TRANSACTION"			 * command, but the user hasn't done anything else yet, so we			 * change to the "transaction block in progress" state and			 * return.			 */		case TBLOCK_BEGIN:			s->blockState = TBLOCK_INPROGRESS;			break;			/*			 * This is the case when we have finished executing a command			 * someplace within a transaction block.  We increment the			 * command counter and return.			 */		case TBLOCK_INPROGRESS:			CommandCounterIncrement();			break;			/*			 * This is the case when we just got the "END TRANSACTION"			 * statement, so we commit the transaction and go back to the			 * default state.			 */		case TBLOCK_END:			CommitTransaction();			s->blockState = TBLOCK_DEFAULT;			break;			/*			 * Here we are in the middle of a transaction block but one of			 * the commands caused an abort so we do nothing but remain in			 * the abort state.  Eventually we will get to the "END			 * TRANSACTION" which will set things straight.			 */		case TBLOCK_ABORT:			break;			/*			 * Here we were in an aborted transaction block which just			 * processed the "END TRANSACTION" command from the user, so			 * clean up and return to the default state.			 */		case TBLOCK_ENDABORT:			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;	}}/* *	AbortCurrentTransaction */voidAbortCurrentTransaction(void){	TransactionState s = CurrentTransactionState;	switch (s->blockState)	{			/*			 * if we aren't in a transaction block, we just do the basic			 * abort & cleanup transaction.			 */		case TBLOCK_DEFAULT:			AbortTransaction();			CleanupTransaction();			break;			/*			 * If we are in the TBLOCK_BEGIN it means something screwed up			 * right after reading "BEGIN TRANSACTION" so we enter the			 * abort state.  Eventually an "END TRANSACTION" will fix			 * things.			 */		case TBLOCK_BEGIN:			s->blockState = TBLOCK_ABORT;			AbortTransaction();			/* CleanupTransaction happens when we exit TBLOCK_ABORT */			break;			/*			 * This is the case when are somewhere in a transaction block			 * which aborted so we abort the transaction and set the ABORT			 * state.  Eventually an "END TRANSACTION" will fix things and			 * restore us to a normal state.			 */		case TBLOCK_INPROGRESS:			s->blockState = TBLOCK_ABORT;			AbortTransaction();			/* CleanupTransaction happens when we exit TBLOCK_ABORT */			break;			/*			 * Here, the system was fouled up just after the user wanted			 * to end the transaction block so we abort the transaction			 * and put us back into the default state.			 */		case TBLOCK_END:			s->blockState = TBLOCK_DEFAULT;			AbortTransaction();			CleanupTransaction();			break;			/*			 * Here, we are already in an aborted transaction state and			 * are waiting for an "END TRANSACTION" to come along and lo			 * and behold, we abort again! So we just remain in the abort			 * state.			 */		case TBLOCK_ABORT:			break;			/*			 * Here we were in an aborted transaction block which just			 * processed the "END TRANSACTION" command but somehow aborted			 * again.. since we must have done the abort processing, we			 * clean up and return to the default state.			 */		case TBLOCK_ENDABORT:			CleanupTransaction();			s->blockState = TBLOCK_DEFAULT;			break;	}}/* *	PreventTransactionChain * *	This routine is to be called by statements that must not run inside *	a transaction block, typically because they have non-rollback-able *	side effects or do internal commits. * *	If we have already started a transaction block, issue an error; also issue *	an error if we appear to be running inside a user-defined function (which *	could issue more commands and possibly cause a failure after the statement *	completes). * *	stmtNode: pointer to parameter block for statement; this is used in *	a very klugy way to determine whether we are inside a function. *	stmtType: statement type name for error messages. */voidPreventTransactionChain(void *stmtNode, const char *stmtType){	/*	 * xact block already started?	 */	if (IsTransactionBlock())		ereport(ERROR,

⌨️ 快捷键说明

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