#include "postgres.h"
#include <time.h>
#include <unistd.h>
#include "access/multixact.h"
#include "access/subtrans.h"
#include "access/transam.h"
#include "access/twophase.h"
#include "access/xact.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/storage.h"
#include "commands/async.h"
#include "commands/tablecmds.h"
#include "commands/trigger.h"
#include "executor/spi.h"
#include "libpq/be-fsstubs.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "replication/walsender.h"
#include "replication/syncrep.h"
#include "storage/fd.h"
#include "storage/lmgr.h"
#include "storage/predicate.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/sinvaladt.h"
#include "storage/smgr.h"
#include "utils/catcache.h"
#include "utils/combocid.h"
#include "utils/guc.h"
#include "utils/inval.h"
#include "utils/memutils.h"
#include "utils/relmapper.h"
#include "utils/snapmgr.h"
#include "utils/timestamp.h"
#include "pg_trace.h"
Go to the source code of this file.
typedef struct SubXactCallbackItem SubXactCallbackItem |
typedef enum TBlockState TBlockState |
typedef TransactionStateData* TransactionState |
typedef struct TransactionStateData TransactionStateData |
typedef enum TransState TransState |
typedef struct XactCallbackItem XactCallbackItem |
enum TBlockState |
Definition at line 100 of file xact.c.
{ /* not-in-transaction-block states */ TBLOCK_DEFAULT, /* idle */ TBLOCK_STARTED, /* running single-query transaction */ /* transaction block states */ TBLOCK_BEGIN, /* starting transaction block */ TBLOCK_INPROGRESS, /* live transaction */ TBLOCK_END, /* COMMIT received */ TBLOCK_ABORT, /* failed xact, awaiting ROLLBACK */ TBLOCK_ABORT_END, /* failed xact, ROLLBACK received */ TBLOCK_ABORT_PENDING, /* live xact, ROLLBACK received */ TBLOCK_PREPARE, /* live xact, PREPARE received */ /* subtransaction states */ TBLOCK_SUBBEGIN, /* starting a subtransaction */ TBLOCK_SUBINPROGRESS, /* live subtransaction */ TBLOCK_SUBRELEASE, /* RELEASE received */ TBLOCK_SUBCOMMIT, /* COMMIT received while TBLOCK_SUBINPROGRESS */ TBLOCK_SUBABORT, /* failed subxact, awaiting ROLLBACK */ TBLOCK_SUBABORT_END, /* failed subxact, ROLLBACK received */ TBLOCK_SUBABORT_PENDING, /* live subxact, ROLLBACK received */ TBLOCK_SUBRESTART, /* live subxact, ROLLBACK TO received */ TBLOCK_SUBABORT_RESTART /* failed subxact, ROLLBACK TO received */ } TBlockState;
enum TransState |
Definition at line 84 of file xact.c.
{ TRANS_DEFAULT, /* idle */ TRANS_START, /* transaction starting */ TRANS_INPROGRESS, /* inside a valid transaction */ TRANS_COMMIT, /* commit in progress */ TRANS_ABORT, /* abort in progress */ TRANS_PREPARE /* prepare in progress */ } TransState;
void AbortCurrentTransaction | ( | void | ) |
Definition at line 2745 of file xact.c.
References AbortCurrentTransaction(), AbortSubTransaction(), AbortTransaction(), TransactionStateData::blockState, CleanupSubTransaction(), CleanupTransaction(), TransactionStateData::state, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, TBLOCK_SUBRESTART, TRANS_DEFAULT, and TRANS_START.
Referenced by AbortCurrentTransaction(), AutoVacLauncherMain(), and PostgresMain().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { case TBLOCK_DEFAULT: if (s->state == TRANS_DEFAULT) { /* we are idle, so nothing to do */ } else { /* * We can get here after an error during transaction start * (state will be TRANS_START). Need to clean up the * incompletely started transaction. First, adjust the * low-level state to suppress warning message from * AbortTransaction. */ if (s->state == TRANS_START) s->state = TRANS_INPROGRESS; AbortTransaction(); CleanupTransaction(); } break; /* * if we aren't in a transaction block, we just do the basic abort * & cleanup transaction. */ case TBLOCK_STARTED: AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * If we are in TBLOCK_BEGIN it means something screwed up right * after reading "BEGIN TRANSACTION". We assume that the user * will interpret the error as meaning the BEGIN failed to get him * into a transaction block, so we should abort and return to idle * state. */ case TBLOCK_BEGIN: AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * We are somewhere in a transaction block and we've gotten a * failure, so we abort the transaction and set up the persistent * ABORT state. We will stay in ABORT until we get a ROLLBACK. */ case TBLOCK_INPROGRESS: AbortTransaction(); s->blockState = TBLOCK_ABORT; /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */ break; /* * Here, we failed while trying to COMMIT. Clean up the * transaction and return to idle state (we do not want to stay in * the transaction). */ case TBLOCK_END: AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * Here, we are already in an aborted transaction state and are * waiting for a ROLLBACK, but for some reason we failed again! So * we just remain in the abort state. */ case TBLOCK_ABORT: case TBLOCK_SUBABORT: break; /* * We are in a failed transaction and we got the ROLLBACK command. * We have already aborted, we just need to cleanup and go to idle * state. */ case TBLOCK_ABORT_END: CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * We are in a live transaction and we got a ROLLBACK command. * Abort, cleanup, go to idle state. */ case TBLOCK_ABORT_PENDING: AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * Here, we failed while trying to PREPARE. Clean up the * transaction and return to idle state (we do not want to stay in * the transaction). */ case TBLOCK_PREPARE: AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * We got an error inside a subtransaction. Abort just the * subtransaction, and go to the persistent SUBABORT state until * we get ROLLBACK. */ case TBLOCK_SUBINPROGRESS: AbortSubTransaction(); s->blockState = TBLOCK_SUBABORT; break; /* * If we failed while trying to create a subtransaction, clean up * the broken subtransaction and abort the parent. The same * applies if we get a failure while ending a subtransaction. */ case TBLOCK_SUBBEGIN: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: AbortSubTransaction(); CleanupSubTransaction(); AbortCurrentTransaction(); break; /* * Same as above, except the Abort() was already done. */ case TBLOCK_SUBABORT_END: case TBLOCK_SUBABORT_RESTART: CleanupSubTransaction(); AbortCurrentTransaction(); break; } }
void AbortOutOfAnyTransaction | ( | void | ) |
Definition at line 3862 of file xact.c.
References AbortSubTransaction(), AbortTransaction(), Assert, TransactionStateData::blockState, CleanupSubTransaction(), CleanupTransaction(), NULL, TransactionStateData::parent, TransactionStateData::state, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, TBLOCK_SUBRESTART, TRANS_DEFAULT, and TRANS_START.
Referenced by do_autovacuum(), RemoveTempRelationsCallback(), and ShutdownPostgres().
{ TransactionState s = CurrentTransactionState; /* * Get out of any transaction or nested transaction */ do { switch (s->blockState) { case TBLOCK_DEFAULT: if (s->state == TRANS_DEFAULT) { /* Not in a transaction, do nothing */ } else { /* * We can get here after an error during transaction start * (state will be TRANS_START). Need to clean up the * incompletely started transaction. First, adjust the * low-level state to suppress warning message from * AbortTransaction. */ if (s->state == TRANS_START) s->state = TRANS_INPROGRESS; AbortTransaction(); CleanupTransaction(); } break; case TBLOCK_STARTED: case TBLOCK_BEGIN: case TBLOCK_INPROGRESS: case TBLOCK_END: case TBLOCK_ABORT_PENDING: case TBLOCK_PREPARE: /* In a transaction, so clean up */ AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; case TBLOCK_ABORT: case TBLOCK_ABORT_END: /* AbortTransaction already done, still need Cleanup */ CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * In a subtransaction, so clean it up and abort parent too */ case TBLOCK_SUBBEGIN: case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: AbortSubTransaction(); CleanupSubTransaction(); s = CurrentTransactionState; /* changed by pop */ break; case TBLOCK_SUBABORT: case TBLOCK_SUBABORT_END: case TBLOCK_SUBABORT_RESTART: /* As above, but AbortSubTransaction already done */ CleanupSubTransaction(); s = CurrentTransactionState; /* changed by pop */ break; } } while (s->blockState != TBLOCK_DEFAULT); /* Should be out of all subxacts now */ Assert(s->parent == NULL); }
static void AbortSubTransaction | ( | void | ) | [static] |
Definition at line 4177 of file xact.c.
References AbortBufferIO(), AfterTriggerEndSubXact(), AtEOSubXact_Files(), AtEOSubXact_HashTables(), AtEOSubXact_Inval(), AtEOSubXact_LargeObject(), AtEOSubXact_Namespace(), AtEOSubXact_on_commit_actions(), AtEOSubXact_PgStat(), AtEOSubXact_RelationCache(), AtEOSubXact_SPI(), AtEOXact_GUC(), AtSubAbort_childXids(), AtSubAbort_Memory(), AtSubAbort_Notify(), AtSubAbort_Portals(), AtSubAbort_ResourceOwner(), AtSubAbort_smgr(), AtSubAbort_Snapshot(), CallSubXactCallbacks(), TransactionStateData::curTransactionOwner, elog, TransactionStateData::gucNestLevel, HOLD_INTERRUPTS, LockErrorCleanup(), LWLockReleaseAll(), TransactionStateData::nestingLevel, TransactionStateData::parent, TransactionStateData::prevSecContext, TransactionStateData::prevUser, TransactionStateData::prevXactReadOnly, RecordTransactionAbort(), RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerRelease(), RESUME_INTERRUPTS, SetUserIdAndSecContext(), ShowTransactionState(), TransactionStateData::state, TransactionStateData::subTransactionId, SUBXACT_EVENT_ABORT_SUB, TRANS_INPROGRESS, TransactionStateData::transactionId, TransactionIdIsValid, TransStateAsString(), UnlockBuffers(), WARNING, and XactReadOnly.
Referenced by AbortCurrentTransaction(), AbortOutOfAnyTransaction(), CommitTransactionCommand(), and RollbackAndReleaseCurrentSubTransaction().
{ TransactionState s = CurrentTransactionState; /* Prevent cancel/die interrupt while cleaning up */ HOLD_INTERRUPTS(); /* Make sure we have a valid memory context and resource owner */ AtSubAbort_Memory(); AtSubAbort_ResourceOwner(); /* * 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! * * FIXME This may be incorrect --- Are there some locks we should keep? * Buffer locks, for example? I don't think so but I'm not sure. */ LWLockReleaseAll(); AbortBufferIO(); UnlockBuffers(); LockErrorCleanup(); /* * check the current transaction state */ ShowTransactionState("AbortSubTransaction"); if (s->state != TRANS_INPROGRESS) elog(WARNING, "AbortSubTransaction while in %s state", TransStateAsString(s->state)); s->state = TRANS_ABORT; /* * Reset user ID which might have been changed transiently. (See notes in * AbortTransaction.) */ SetUserIdAndSecContext(s->prevUser, s->prevSecContext); /* * We can skip all this stuff if the subxact failed before creating a * ResourceOwner... */ if (s->curTransactionOwner) { AfterTriggerEndSubXact(false); AtSubAbort_Portals(s->subTransactionId, s->parent->subTransactionId, s->parent->curTransactionOwner); AtEOSubXact_LargeObject(false, s->subTransactionId, s->parent->subTransactionId); AtSubAbort_Notify(); /* Advertise the fact that we aborted in pg_clog. */ (void) RecordTransactionAbort(true); /* Post-abort cleanup */ if (TransactionIdIsValid(s->transactionId)) AtSubAbort_childXids(); CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId, s->parent->subTransactionId); ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, false); AtEOSubXact_RelationCache(false, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_Inval(false); ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_LOCKS, false, false); ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_AFTER_LOCKS, false, false); AtSubAbort_smgr(); AtEOXact_GUC(false, s->gucNestLevel); AtEOSubXact_SPI(false, s->subTransactionId); AtEOSubXact_on_commit_actions(false, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_Namespace(false, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_Files(false, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_HashTables(false, s->nestingLevel); AtEOSubXact_PgStat(false, s->nestingLevel); AtSubAbort_Snapshot(s->nestingLevel); } /* * Restore the upper transaction's read-only state, too. This should be * redundant with GUC's cleanup but we may as well do it for consistency * with the commit case. */ XactReadOnly = s->prevXactReadOnly; RESUME_INTERRUPTS(); }
static void AbortTransaction | ( | void | ) | [static] |
Definition at line 2267 of file xact.c.
References AbortBufferIO(), AfterTriggerEndXact(), Assert, AtAbort_Memory(), AtAbort_Notify(), AtAbort_Portals(), AtAbort_ResourceOwner(), AtEOXact_Buffers(), AtEOXact_CatCache(), AtEOXact_ComboCid(), AtEOXact_Files(), AtEOXact_GUC(), AtEOXact_HashTables(), AtEOXact_Inval(), AtEOXact_LargeObject(), AtEOXact_MultiXact(), AtEOXact_Namespace(), AtEOXact_on_commit_actions(), AtEOXact_PgStat(), AtEOXact_RelationCache(), AtEOXact_RelationMap(), AtEOXact_SMgr(), AtEOXact_SPI(), CallXactCallbacks(), elog, HOLD_INTERRUPTS, LockErrorCleanup(), LWLockReleaseAll(), PGPROC::lxid, MyProc, NULL, TransactionStateData::parent, pgstat_report_xact_timestamp(), TransactionStateData::prevSecContext, TransactionStateData::prevUser, ProcArrayEndTransaction(), RecordTransactionAbort(), RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerRelease(), RESUME_INTERRUPTS, SetUserIdAndSecContext(), smgrDoPendingDeletes(), TransactionStateData::state, TopTransactionResourceOwner, TRANS_INPROGRESS, TRANS_PREPARE, TransStateAsString(), UnlockBuffers(), WARNING, and XACT_EVENT_ABORT.
Referenced by AbortCurrentTransaction(), AbortOutOfAnyTransaction(), and CommitTransactionCommand().
{ TransactionState s = CurrentTransactionState; TransactionId latestXid; /* Prevent cancel/die interrupt while cleaning up */ HOLD_INTERRUPTS(); /* Make sure we have a valid memory context and resource owner */ AtAbort_Memory(); AtAbort_ResourceOwner(); /* * 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. */ LockErrorCleanup(); /* * check the current transaction state */ if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE) elog(WARNING, "AbortTransaction while in %s state", TransStateAsString(s->state)); Assert(s->parent == NULL); /* * set the current transaction state information appropriately during the * abort processing */ s->state = TRANS_ABORT; /* * Reset user ID which might have been changed transiently. We need this * to clean up in case control escaped out of a SECURITY DEFINER function * or other local change of CurrentUserId; therefore, the prior value of * SecurityRestrictionContext also needs to be restored. * * (Note: it is not necessary to restore session authorization or role * settings here because those can only be changed via GUC, and GUC will * take care of rolling them back if need be.) */ SetUserIdAndSecContext(s->prevUser, s->prevSecContext); /* * do abort processing */ AfterTriggerEndXact(false); /* 'false' means it's abort */ AtAbort_Portals(); AtEOXact_LargeObject(false); AtAbort_Notify(); AtEOXact_RelationMap(false); /* * Advertise the fact that we aborted in pg_clog (assuming that we got as * far as assigning an XID to advertise). */ latestXid = RecordTransactionAbort(false); TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->lxid); /* * Let others know about no transaction in progress by me. Note that this * must be done _before_ releasing locks we hold and _after_ * RecordTransactionAbort. */ ProcArrayEndTransaction(MyProc, latestXid); /* * Post-abort cleanup. See notes in CommitTransaction() concerning * ordering. We can skip all of it if the transaction failed before * creating a resource owner. */ if (TopTransactionResourceOwner != NULL) { CallXactCallbacks(XACT_EVENT_ABORT); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true); AtEOXact_Buffers(false); AtEOXact_RelationCache(false); AtEOXact_Inval(false); AtEOXact_MultiXact(); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_LOCKS, false, true); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_AFTER_LOCKS, false, true); smgrDoPendingDeletes(false); AtEOXact_CatCache(false); AtEOXact_GUC(false, 1); AtEOXact_SPI(false); AtEOXact_on_commit_actions(false); AtEOXact_Namespace(false); AtEOXact_SMgr(); AtEOXact_Files(); AtEOXact_ComboCid(); AtEOXact_HashTables(false); AtEOXact_PgStat(false); pgstat_report_xact_timestamp(0); } /* * State remains TRANS_ABORT until CleanupTransaction(). */ RESUME_INTERRUPTS(); }
static void AssignTransactionId | ( | TransactionState | s | ) | [static] |
Definition at line 430 of file xact.c.
References Assert, XLogRecData::buffer, CurrentResourceOwner, TransactionStateData::curTransactionOwner, XLogRecData::data, GetNewTransactionId(), GetTopTransactionId(), XLogRecData::len, TransactionStateData::nestingLevel, XLogRecData::next, xl_xact_assignment::nsubxacts, NULL, nUnreportedXids, palloc(), TransactionStateData::parent, pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PGPROC_MAX_CACHED_SUBXIDS, RegisterPredicateLockingXid(), TransactionStateData::state, SubTransSetParent(), TRANS_INPROGRESS, TransactionStateData::transactionId, TransactionIdIsValid, unreportedXids, XactLockTableInsert(), XLOG_XACT_ASSIGNMENT, XLogInsert(), XLogStandbyInfoActive, and xl_xact_assignment::xtop.
Referenced by GetCurrentTransactionId(), and GetTopTransactionId().
{ bool isSubXact = (s->parent != NULL); ResourceOwner currentOwner; /* Assert that caller didn't screw up */ Assert(!TransactionIdIsValid(s->transactionId)); Assert(s->state == TRANS_INPROGRESS); /* * Ensure parent(s) have XIDs, so that a child always has an XID later * than its parent. Musn't recurse here, or we might get a stack overflow * if we're at the bottom of a huge stack of subtransactions none of which * have XIDs yet. */ if (isSubXact && !TransactionIdIsValid(s->parent->transactionId)) { TransactionState p = s->parent; TransactionState *parents; size_t parentOffset = 0; parents = palloc(sizeof(TransactionState) * s->nestingLevel); while (p != NULL && !TransactionIdIsValid(p->transactionId)) { parents[parentOffset++] = p; p = p->parent; } /* * This is technically a recursive call, but the recursion will never * be more than one layer deep. */ while (parentOffset != 0) AssignTransactionId(parents[--parentOffset]); pfree(parents); } /* * Generate a new Xid and record it in PG_PROC and pg_subtrans. * * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in * shared storage other than PG_PROC; because if there's no room for it in * PG_PROC, the subtrans entry is needed to ensure that other backends see * the Xid as "running". See GetNewTransactionId. */ s->transactionId = GetNewTransactionId(isSubXact); if (isSubXact) SubTransSetParent(s->transactionId, s->parent->transactionId, false); /* * If it's a top-level transaction, the predicate locking system needs to * be told about it too. */ if (!isSubXact) RegisterPredicateLockingXid(s->transactionId); /* * Acquire lock on the transaction XID. (We assume this cannot block.) We * have to ensure that the lock is assigned to the transaction's own * ResourceOwner. */ currentOwner = CurrentResourceOwner; PG_TRY(); { CurrentResourceOwner = s->curTransactionOwner; XactLockTableInsert(s->transactionId); } PG_CATCH(); { /* Ensure CurrentResourceOwner is restored on error */ CurrentResourceOwner = currentOwner; PG_RE_THROW(); } PG_END_TRY(); CurrentResourceOwner = currentOwner; /* * Every PGPROC_MAX_CACHED_SUBXIDS assigned transaction ids within each * top-level transaction we issue a WAL record for the assignment. We * include the top-level xid and all the subxids that have not yet been * reported using XLOG_XACT_ASSIGNMENT records. * * This is required to limit the amount of shared memory required in a hot * standby server to keep track of in-progress XIDs. See notes for * RecordKnownAssignedTransactionIds(). * * We don't keep track of the immediate parent of each subxid, only the * top-level transaction that each subxact belongs to. This is correct in * recovery only because aborted subtransactions are separately WAL * logged. */ if (isSubXact && XLogStandbyInfoActive()) { unreportedXids[nUnreportedXids] = s->transactionId; nUnreportedXids++; /* * ensure this test matches similar one in * RecoverPreparedTransactions() */ if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS) { XLogRecData rdata[2]; xl_xact_assignment xlrec; /* * xtop is always set by now because we recurse up transaction * stack to the highest unassigned xid and then come back down */ xlrec.xtop = GetTopTransactionId(); Assert(TransactionIdIsValid(xlrec.xtop)); xlrec.nsubxacts = nUnreportedXids; rdata[0].data = (char *) &xlrec; rdata[0].len = MinSizeOfXactAssignment; rdata[0].buffer = InvalidBuffer; rdata[0].next = &rdata[1]; rdata[1].data = (char *) unreportedXids; rdata[1].len = PGPROC_MAX_CACHED_SUBXIDS * sizeof(TransactionId); rdata[1].buffer = InvalidBuffer; rdata[1].next = NULL; (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT, rdata); nUnreportedXids = 0; } } }
static void AtAbort_Memory | ( | void | ) | [static] |
Definition at line 1515 of file xact.c.
References MemoryContextSwitchTo(), NULL, and TopMemoryContext.
Referenced by AbortTransaction().
{ /* * 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); }
static void AtAbort_ResourceOwner | ( | void | ) | [static] |
Definition at line 1547 of file xact.c.
References CurrentResourceOwner, and TopTransactionResourceOwner.
Referenced by AbortTransaction().
{ /* * Make sure we have a valid ResourceOwner, if possible (else it will be * NULL, which is OK) */ CurrentResourceOwner = TopTransactionResourceOwner; }
static void AtCCI_LocalCache | ( | void | ) | [static] |
Definition at line 1216 of file xact.c.
References AtCCI_RelationMap(), and CommandEndInvalidationMessages().
Referenced by CommandCounterIncrement().
{ /* * Make any pending relation map changes visible. We must do this before * processing local sinval messages, so that the map changes will get * reflected into the relcache when relcache invals are processed. */ AtCCI_RelationMap(); /* * Make catalog changes visible to me for the next command. */ CommandEndInvalidationMessages(); }
static void AtCleanup_Memory | ( | void | ) | [static] |
Definition at line 1605 of file xact.c.
References Assert, TransactionStateData::curTransactionContext, CurTransactionContext, MemoryContextDelete(), MemoryContextResetAndDeleteChildren(), MemoryContextSwitchTo(), NULL, TransactionStateData::parent, TopMemoryContext, and TopTransactionContext.
Referenced by CleanupTransaction().
{ Assert(CurrentTransactionState->parent == NULL); /* * 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); /* * Clear the special abort context for next time. */ if (TransactionAbortContext != NULL) MemoryContextResetAndDeleteChildren(TransactionAbortContext); /* * Release all transaction-local memory. */ if (TopTransactionContext != NULL) MemoryContextDelete(TopTransactionContext); TopTransactionContext = NULL; CurTransactionContext = NULL; CurrentTransactionState->curTransactionContext = NULL; }
static void AtCommit_Memory | ( | void | ) | [static] |
Definition at line 1235 of file xact.c.
References Assert, TransactionStateData::curTransactionContext, CurTransactionContext, MemoryContextDelete(), MemoryContextSwitchTo(), NULL, TopMemoryContext, and TopTransactionContext.
Referenced by CommitTransaction(), and PrepareTransaction().
{ /* * 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; }
static void AtStart_Cache | ( | void | ) | [static] |
Definition at line 813 of file xact.c.
References AcceptInvalidationMessages().
Referenced by StartTransaction().
{ AcceptInvalidationMessages(); }
static void AtStart_Memory | ( | void | ) | [static] |
Definition at line 822 of file xact.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, TransactionStateData::curTransactionContext, CurTransactionContext, MemoryContextSwitchTo(), NULL, TopMemoryContext, and TopTransactionContext.
Referenced by StartTransaction().
{ TransactionState s = CurrentTransactionState; /* * If this is the first time through, create a private context for * AbortTransaction to work in. By reserving some space now, we can * insulate AbortTransaction from out-of-memory scenarios. Like * ErrorContext, we set it up with slow growth rate and a nonzero minimum * size, so that space will be reserved immediately. */ if (TransactionAbortContext == NULL) TransactionAbortContext = AllocSetContextCreate(TopMemoryContext, "TransactionAbortContext", 32 * 1024, 32 * 1024, 32 * 1024); /* * We shouldn't have a transaction context already. */ Assert(TopTransactionContext == NULL); /* * Create a toplevel context for the transaction. */ TopTransactionContext = AllocSetContextCreate(TopMemoryContext, "TopTransactionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); /* * In a top-level transaction, CurTransactionContext is the same as * TopTransactionContext. */ CurTransactionContext = TopTransactionContext; s->curTransactionContext = CurTransactionContext; /* Make the CurTransactionContext active. */ MemoryContextSwitchTo(CurTransactionContext); }
static void AtStart_ResourceOwner | ( | void | ) | [static] |
Definition at line 871 of file xact.c.
References Assert, CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, NULL, ResourceOwnerCreate(), and TopTransactionResourceOwner.
Referenced by StartTransaction().
{ TransactionState s = CurrentTransactionState; /* * We shouldn't have a transaction resource owner already. */ Assert(TopTransactionResourceOwner == NULL); /* * Create a toplevel resource owner for the transaction. */ s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction"); TopTransactionResourceOwner = s->curTransactionOwner; CurTransactionResourceOwner = s->curTransactionOwner; CurrentResourceOwner = s->curTransactionOwner; }
static void AtSubAbort_childXids | ( | void | ) | [static] |
Definition at line 1573 of file xact.c.
References TransactionStateData::childXids, TransactionStateData::maxChildXids, TransactionStateData::nChildXids, NULL, and pfree().
Referenced by AbortSubTransaction().
{ 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; /* * We could prune the unreportedXids array here. But we don't bother. That * would potentially reduce number of XLOG_XACT_ASSIGNMENT records but it * would likely introduce more CPU time into the more common paths, so we * choose not to do that. */ }
static void AtSubAbort_Memory | ( | void | ) | [static] |
Definition at line 1535 of file xact.c.
References Assert, MemoryContextSwitchTo(), and NULL.
Referenced by AbortSubTransaction().
static void AtSubAbort_ResourceOwner | ( | void | ) | [static] |
Definition at line 1560 of file xact.c.
References CurrentResourceOwner, and TransactionStateData::curTransactionOwner.
Referenced by AbortSubTransaction().
{ TransactionState s = CurrentTransactionState; /* Make sure we have a valid ResourceOwner */ CurrentResourceOwner = s->curTransactionOwner; }
static void AtSubCleanup_Memory | ( | void | ) | [static] |
Definition at line 1641 of file xact.c.
References Assert, CurTransactionContext, TransactionStateData::curTransactionContext, MemoryContextDelete(), MemoryContextResetAndDeleteChildren(), MemoryContextSwitchTo(), NULL, and TransactionStateData::parent.
Referenced by CleanupSubTransaction().
{ TransactionState s = CurrentTransactionState; Assert(s->parent != NULL); /* Make sure we're not in an about-to-be-deleted context */ MemoryContextSwitchTo(s->parent->curTransactionContext); CurTransactionContext = s->parent->curTransactionContext; /* * Clear the special abort context for next time. */ if (TransactionAbortContext != NULL) MemoryContextResetAndDeleteChildren(TransactionAbortContext); /* * Delete the subxact local memory contexts. Its CurTransactionContext can * go too (note this also kills CurTransactionContexts from any children * of the subxact). */ if (s->curTransactionContext) MemoryContextDelete(s->curTransactionContext); s->curTransactionContext = NULL; }
static void AtSubCommit_childXids | ( | void | ) | [static] |
Definition at line 1291 of file xact.c.
References Assert, TransactionStateData::childXids, ereport, errcode(), errmsg(), ERROR, MaxAllocSize, TransactionStateData::maxChildXids, MemoryContextAlloc(), Min, TransactionStateData::nChildXids, NULL, TransactionStateData::parent, pfree(), repalloc(), TopTransactionContext, and TransactionStateData::transactionId.
Referenced by CommitSubTransaction().
{ 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; }
static void AtSubCommit_Memory | ( | void | ) | [static] |
Definition at line 1262 of file xact.c.
References Assert, TransactionStateData::curTransactionContext, CurTransactionContext, MemoryContextDelete(), MemoryContextIsEmpty(), MemoryContextSwitchTo(), NULL, and TransactionStateData::parent.
Referenced by CommitSubTransaction().
{ 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; } }
static void AtSubStart_Memory | ( | void | ) | [static] |
Definition at line 899 of file xact.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, TransactionStateData::curTransactionContext, CurTransactionContext, MemoryContextSwitchTo(), and NULL.
Referenced by StartSubTransaction().
{ TransactionState s = CurrentTransactionState; Assert(CurTransactionContext != NULL); /* * Create a CurTransactionContext, which will be used to hold data that * survives subtransaction commit but disappears on subtransaction abort. * We make it a child of the immediate parent's CurTransactionContext. */ CurTransactionContext = AllocSetContextCreate(CurTransactionContext, "CurTransactionContext", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); s->curTransactionContext = CurTransactionContext; /* Make the CurTransactionContext active. */ MemoryContextSwitchTo(CurTransactionContext); }
static void AtSubStart_ResourceOwner | ( | void | ) | [static] |
Definition at line 925 of file xact.c.
References Assert, CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, NULL, TransactionStateData::parent, and ResourceOwnerCreate().
Referenced by StartSubTransaction().
{ TransactionState s = CurrentTransactionState; Assert(s->parent != NULL); /* * Create a resource owner for the subtransaction. We make it a child of * the immediate parent's resource owner. */ s->curTransactionOwner = ResourceOwnerCreate(s->parent->curTransactionOwner, "SubTransaction"); CurTransactionResourceOwner = s->curTransactionOwner; CurrentResourceOwner = s->curTransactionOwner; }
void BeginInternalSubTransaction | ( | char * | name | ) |
Definition at line 3730 of file xact.c.
References TransactionStateData::blockState, BlockStateAsString(), CommitTransactionCommand(), elog, FATAL, MemoryContextStrdup(), TransactionStateData::name, PushTransaction(), StartTransactionCommand(), TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, TBLOCK_SUBRESTART, and TopTransactionContext.
Referenced by exec_stmt_block(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), pltcl_subtrans_begin(), PLy_spi_subtransaction_begin(), and PLy_subtransaction_enter().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { case TBLOCK_STARTED: case TBLOCK_INPROGRESS: case TBLOCK_END: case TBLOCK_PREPARE: case TBLOCK_SUBINPROGRESS: /* Normal subtransaction start */ PushTransaction(); s = CurrentTransactionState; /* changed by push */ /* * Savepoint names, like the TransactionState block itself, live * in TopTransactionContext. */ if (name) s->name = MemoryContextStrdup(TopTransactionContext, name); break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT: case TBLOCK_SUBABORT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: elog(FATAL, "BeginInternalSubTransaction: unexpected state %s", BlockStateAsString(s->blockState)); break; } CommitTransactionCommand(); StartTransactionCommand(); }
void BeginTransactionBlock | ( | void | ) |
Definition at line 3152 of file xact.c.
References TransactionStateData::blockState, BlockStateAsString(), elog, ereport, errcode(), errmsg(), FATAL, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, TBLOCK_SUBRESTART, and WARNING.
Referenced by standard_ProcessUtility().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { /* * We are not inside a transaction block, so allow one to begin. */ case TBLOCK_STARTED: s->blockState = TBLOCK_BEGIN; break; /* * Already a transaction block in progress. */ case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: case TBLOCK_ABORT: case TBLOCK_SUBABORT: ereport(WARNING, (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), errmsg("there is already a transaction in progress"))); break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "BeginTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; } }
static const char * BlockStateAsString | ( | TBlockState | blockState | ) | [static] |
Definition at line 4465 of file xact.c.
References TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by BeginInternalSubTransaction(), BeginTransactionBlock(), CommitTransactionCommand(), DefineSavepoint(), EndTransactionBlock(), ReleaseCurrentSubTransaction(), ReleaseSavepoint(), RollbackAndReleaseCurrentSubTransaction(), RollbackToSavepoint(), ShowTransactionStateRec(), StartTransactionCommand(), TransactionBlockStatusCode(), and UserAbortTransactionBlock().
{ switch (blockState) { case TBLOCK_DEFAULT: return "DEFAULT"; case TBLOCK_STARTED: return "STARTED"; case TBLOCK_BEGIN: return "BEGIN"; case TBLOCK_INPROGRESS: return "INPROGRESS"; case TBLOCK_END: return "END"; case TBLOCK_ABORT: return "ABORT"; case TBLOCK_ABORT_END: return "ABORT END"; case TBLOCK_ABORT_PENDING: return "ABORT PEND"; case TBLOCK_PREPARE: return "PREPARE"; case TBLOCK_SUBBEGIN: return "SUB BEGIN"; case TBLOCK_SUBINPROGRESS: return "SUB INPROGRS"; case TBLOCK_SUBRELEASE: return "SUB RELEASE"; case TBLOCK_SUBCOMMIT: return "SUB COMMIT"; case TBLOCK_SUBABORT: return "SUB ABORT"; case TBLOCK_SUBABORT_END: return "SUB ABORT END"; case TBLOCK_SUBABORT_PENDING: return "SUB ABRT PEND"; case TBLOCK_SUBRESTART: return "SUB RESTART"; case TBLOCK_SUBABORT_RESTART: return "SUB AB RESTRT"; } return "UNRECOGNIZED"; }
static void CallSubXactCallbacks | ( | SubXactEvent | event, | |
SubTransactionId | mySubid, | |||
SubTransactionId | parentSubid | |||
) | [static] |
Definition at line 3131 of file xact.c.
References SubXactCallbackItem::arg, SubXactCallbackItem::callback, and SubXactCallbackItem::next.
Referenced by AbortSubTransaction(), CommitSubTransaction(), and StartSubTransaction().
{ SubXactCallbackItem *item; for (item = SubXact_callbacks; item; item = item->next) (*item->callback) (event, mySubid, parentSubid, item->arg); }
static void CallXactCallbacks | ( | XactEvent | event | ) | [static] |
Definition at line 3076 of file xact.c.
References XactCallbackItem::arg, XactCallbackItem::callback, and XactCallbackItem::next.
Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().
{ XactCallbackItem *item; for (item = Xact_callbacks; item; item = item->next) (*item->callback) (event, item->arg); }
static void CleanupSubTransaction | ( | void | ) | [static] |
Definition at line 4289 of file xact.c.
References AtSubCleanup_Memory(), AtSubCleanup_Portals(), CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, elog, TransactionStateData::parent, PopTransaction(), ResourceOwnerDelete(), ShowTransactionState(), TransactionStateData::state, TransactionStateData::subTransactionId, TRANS_ABORT, TransStateAsString(), and WARNING.
Referenced by AbortCurrentTransaction(), AbortOutOfAnyTransaction(), CommitTransactionCommand(), and RollbackAndReleaseCurrentSubTransaction().
{ TransactionState s = CurrentTransactionState; ShowTransactionState("CleanupSubTransaction"); if (s->state != TRANS_ABORT) elog(WARNING, "CleanupSubTransaction while in %s state", TransStateAsString(s->state)); AtSubCleanup_Portals(s->subTransactionId); CurrentResourceOwner = s->parent->curTransactionOwner; CurTransactionResourceOwner = s->parent->curTransactionOwner; if (s->curTransactionOwner) ResourceOwnerDelete(s->curTransactionOwner); s->curTransactionOwner = NULL; AtSubCleanup_Memory(); s->state = TRANS_DEFAULT; PopTransaction(); }
static void CleanupTransaction | ( | void | ) | [static] |
Definition at line 2394 of file xact.c.
References AtCleanup_Memory(), AtCleanup_Portals(), AtEOXact_Snapshot(), TransactionStateData::childXids, CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, elog, FATAL, TransactionStateData::gucNestLevel, TransactionStateData::maxChildXids, TransactionStateData::nChildXids, TransactionStateData::nestingLevel, ResourceOwnerDelete(), TransactionStateData::state, TransactionStateData::subTransactionId, TopTransactionResourceOwner, TRANS_ABORT, TransactionStateData::transactionId, and TransStateAsString().
Referenced by AbortCurrentTransaction(), AbortOutOfAnyTransaction(), and CommitTransactionCommand().
{ TransactionState s = CurrentTransactionState; /* * State should still be TRANS_ABORT from AbortTransaction(). */ if (s->state != TRANS_ABORT) elog(FATAL, "CleanupTransaction: unexpected state %s", TransStateAsString(s->state)); /* * do abort cleanup processing */ AtCleanup_Portals(); /* now safe to release portal memory */ AtEOXact_Snapshot(false); /* and release the transaction's snapshots */ CurrentResourceOwner = NULL; /* and resource owner */ if (TopTransactionResourceOwner) ResourceOwnerDelete(TopTransactionResourceOwner); s->curTransactionOwner = NULL; CurTransactionResourceOwner = NULL; TopTransactionResourceOwner = NULL; AtCleanup_Memory(); /* and transaction memory */ s->transactionId = InvalidTransactionId; s->subTransactionId = InvalidSubTransactionId; s->nestingLevel = 0; s->gucNestLevel = 0; s->childXids = NULL; s->nChildXids = 0; s->maxChildXids = 0; /* * done with abort processing, set current transaction state back to * default */ s->state = TRANS_DEFAULT; }
void CommandCounterIncrement | ( | void | ) |
Definition at line 758 of file xact.c.
References AtCCI_LocalCache(), currentCommandId, currentCommandIdUsed, ereport, errcode(), errmsg(), ERROR, FirstCommandId, and SnapshotSetCommandId().
Referenced by _SPI_execute_plan(), acquire_inherited_sample_rows(), AddRoleMems(), AlterRole(), ATAddCheckConstraint(), ATExecAddColumn(), ATExecAlterColumnType(), ATExecCmd(), ATExecDropColumn(), ATExecDropConstraint(), ATExecSetTableSpace(), CommitSubTransaction(), CommitTransactionCommand(), create_toast_table(), CreateFKCheckTrigger(), createForeignKeyTriggers(), CreateForeignTable(), CreateRole(), CreateSchemaCommand(), DefineCollation(), DefineDomain(), DefineQueryRewrite(), DefineRange(), DefineRelation(), DefineType(), DefineView(), deleteOneObject(), DelRoleMems(), DropRole(), EventTriggerDDLCommandEnd(), EventTriggerDDLCommandStart(), EventTriggerInvoke(), EventTriggerSQLDrop(), exec_eval_simple_expr(), exec_execute_message(), exec_parse_message(), exec_simple_query(), ExecGrant_Database(), ExecGrant_Fdw(), ExecGrant_ForeignServer(), ExecGrant_Function(), ExecGrant_Language(), ExecGrant_Largeobject(), ExecGrant_Namespace(), ExecGrant_Relation(), ExecGrant_Tablespace(), ExecGrant_Type(), execute_sql_string(), ExplainOnePlan(), findTypeInputFunction(), findTypeOutputFunction(), fmgr_sql(), index_build(), index_create(), InitTempTableNamespace(), intorel_startup(), inv_create(), inv_drop(), inv_truncate(), inv_write(), make_new_heap(), makeConfigurationDependencies(), moveArrayTypeName(), OperatorShellMake(), OperatorUpd(), PortalRunMulti(), PreCommit_on_commit_actions(), ProcedureCreate(), ProcessUtilitySlow(), reindex_relation(), RelationSetNewRelfilenode(), RenumberEnumType(), ri_PerformCheck(), shdepReassignOwned(), SPI_cursor_open_internal(), and StoreConstraints().
{ /* * If the current value of the command counter hasn't been "used" to mark * tuples, we need not increment it, since there's no need to distinguish * a read-only command from others. This helps postpone command counter * overflow, and keeps no-op CommandCounterIncrement operations cheap. */ if (currentCommandIdUsed) { currentCommandId += 1; if (currentCommandId == FirstCommandId) /* check for overflow */ { currentCommandId -= 1; ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot have more than 2^32-1 commands in a transaction"))); } currentCommandIdUsed = false; /* Propagate new command ID into static snapshots */ SnapshotSetCommandId(currentCommandId); /* * Make any catalog changes done by the just-completed command visible * in the local syscache. We obviously don't need to do this after a * read-only command. (But see hacks in inval.c to make real sure we * don't think a command that queued inval messages was read-only.) */ AtCCI_LocalCache(); } }
static void CommitSubTransaction | ( | void | ) | [static] |
Definition at line 4076 of file xact.c.
References AfterTriggerEndSubXact(), AtEOSubXact_Files(), AtEOSubXact_HashTables(), AtEOSubXact_Inval(), AtEOSubXact_LargeObject(), AtEOSubXact_Namespace(), AtEOSubXact_on_commit_actions(), AtEOSubXact_PgStat(), AtEOSubXact_RelationCache(), AtEOSubXact_SPI(), AtEOXact_GUC(), AtSubCommit_childXids(), AtSubCommit_Memory(), AtSubCommit_Notify(), AtSubCommit_Portals(), AtSubCommit_smgr(), AtSubCommit_Snapshot(), CallSubXactCallbacks(), CommandCounterIncrement(), CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, elog, TransactionStateData::gucNestLevel, TransactionStateData::nestingLevel, TransactionStateData::parent, PopTransaction(), TransactionStateData::prevXactReadOnly, RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerDelete(), ResourceOwnerRelease(), ShowTransactionState(), TransactionStateData::state, TransactionStateData::subTransactionId, SUBXACT_EVENT_COMMIT_SUB, SUBXACT_EVENT_PRE_COMMIT_SUB, TRANS_INPROGRESS, TransactionStateData::transactionId, TransactionIdIsValid, TransStateAsString(), WARNING, XactLockTableDelete(), and XactReadOnly.
Referenced by CommitTransactionCommand(), and ReleaseCurrentSubTransaction().
{ TransactionState s = CurrentTransactionState; ShowTransactionState("CommitSubTransaction"); if (s->state != TRANS_INPROGRESS) elog(WARNING, "CommitSubTransaction while in %s state", TransStateAsString(s->state)); /* Pre-commit processing goes here */ CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId, s->parent->subTransactionId); /* Do the actual "commit", such as it is */ s->state = TRANS_COMMIT; /* Must CCI to ensure commands of subtransaction are seen as done */ CommandCounterIncrement(); /* * Prior to 8.4 we marked subcommit in clog at this point. We now only * perform that step, if required, as part of the atomic update of the * whole transaction tree at top level commit or abort. */ /* Post-commit cleanup */ if (TransactionIdIsValid(s->transactionId)) AtSubCommit_childXids(); AfterTriggerEndSubXact(true); AtSubCommit_Portals(s->subTransactionId, s->parent->subTransactionId, s->parent->curTransactionOwner); AtEOSubXact_LargeObject(true, s->subTransactionId, s->parent->subTransactionId); AtSubCommit_Notify(); CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId, s->parent->subTransactionId); ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_BEFORE_LOCKS, true, false); AtEOSubXact_RelationCache(true, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_Inval(true); AtSubCommit_smgr(); /* * The only lock we actually release here is the subtransaction XID lock. */ CurrentResourceOwner = s->curTransactionOwner; if (TransactionIdIsValid(s->transactionId)) XactLockTableDelete(s->transactionId); /* * Other locks should get transferred to their parent resource owner. */ ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_LOCKS, true, false); ResourceOwnerRelease(s->curTransactionOwner, RESOURCE_RELEASE_AFTER_LOCKS, true, false); AtEOXact_GUC(true, s->gucNestLevel); AtEOSubXact_SPI(true, s->subTransactionId); AtEOSubXact_on_commit_actions(true, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_Namespace(true, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_Files(true, s->subTransactionId, s->parent->subTransactionId); AtEOSubXact_HashTables(true, s->nestingLevel); AtEOSubXact_PgStat(true, s->nestingLevel); AtSubCommit_Snapshot(s->nestingLevel); /* * We need to restore the upper transaction's read-only state, in case the * upper is read-write while the child is read-only; GUC will incorrectly * think it should leave the child state in place. */ XactReadOnly = s->prevXactReadOnly; CurrentResourceOwner = s->parent->curTransactionOwner; CurTransactionResourceOwner = s->parent->curTransactionOwner; ResourceOwnerDelete(s->curTransactionOwner); s->curTransactionOwner = NULL; AtSubCommit_Memory(); s->state = TRANS_DEFAULT; PopTransaction(); }
static void CommitTransaction | ( | void | ) | [static] |
Definition at line 1812 of file xact.c.
References AfterTriggerEndXact(), AfterTriggerFireDeferred(), Assert, AtCommit_Memory(), AtCommit_Notify(), AtEOXact_Buffers(), AtEOXact_CatCache(), AtEOXact_ComboCid(), AtEOXact_Files(), AtEOXact_GUC(), AtEOXact_HashTables(), AtEOXact_Inval(), AtEOXact_LargeObject(), AtEOXact_MultiXact(), AtEOXact_Namespace(), AtEOXact_on_commit_actions(), AtEOXact_PgStat(), AtEOXact_RelationCache(), AtEOXact_RelationMap(), AtEOXact_SMgr(), AtEOXact_Snapshot(), AtEOXact_SPI(), CallXactCallbacks(), TransactionStateData::childXids, CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, elog, TransactionStateData::gucNestLevel, HOLD_INTERRUPTS, PGPROC::lxid, TransactionStateData::maxChildXids, MyProc, TransactionStateData::nChildXids, TransactionStateData::nestingLevel, NULL, TransactionStateData::parent, pgstat_report_xact_timestamp(), PreCommit_CheckForSerializationFailure(), PreCommit_Notify(), PreCommit_on_commit_actions(), PreCommit_Portals(), ProcArrayEndTransaction(), RecordTransactionCommit(), RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerDelete(), ResourceOwnerRelease(), RESUME_INTERRUPTS, ShowTransactionState(), smgrDoPendingDeletes(), TransactionStateData::state, TransactionStateData::subTransactionId, TopTransactionResourceOwner, TRANS_INPROGRESS, TransactionStateData::transactionId, TransStateAsString(), WARNING, XACT_EVENT_COMMIT, and XACT_EVENT_PRE_COMMIT.
Referenced by CommitTransactionCommand(), EndRestoreBlobs(), restore_toc_entry(), and RestoreArchive().
{ TransactionState s = CurrentTransactionState; TransactionId latestXid; ShowTransactionState("CommitTransaction"); /* * check the current transaction state */ if (s->state != TRANS_INPROGRESS) elog(WARNING, "CommitTransaction while in %s state", TransStateAsString(s->state)); Assert(s->parent == NULL); /* * Do pre-commit processing that involves calling user-defined code, such * as triggers. Since closing cursors could queue trigger actions, * triggers could open cursors, etc, we have to keep looping until there's * nothing left to do. */ for (;;) { /* * Fire all currently pending deferred triggers. */ AfterTriggerFireDeferred(); /* * Close open portals (converting holdable ones into static portals). * If there weren't any, we are done ... otherwise loop back to check * if they queued deferred triggers. Lather, rinse, repeat. */ if (!PreCommit_Portals(false)) break; } CallXactCallbacks(XACT_EVENT_PRE_COMMIT); /* * The remaining actions cannot call any user-defined code, so it's safe * to start shutting down within-transaction services. But note that most * of this stuff could still throw an error, which would switch us into * the transaction-abort path. */ /* Shut down the deferred-trigger manager */ AfterTriggerEndXact(true); /* * Let ON COMMIT management do its thing (must happen after closing * cursors, to avoid dangling-reference problems) */ PreCommit_on_commit_actions(); /* close large objects before lower-level cleanup */ AtEOXact_LargeObject(true); /* * Mark serializable transaction as complete for predicate locking * purposes. This should be done as late as we can put it and still allow * errors to be raised for failure patterns found at commit. */ PreCommit_CheckForSerializationFailure(); /* * Insert notifications sent by NOTIFY commands into the queue. This * should be late in the pre-commit sequence to minimize time spent * holding the notify-insertion lock. */ PreCommit_Notify(); /* Prevent cancel/die interrupt while cleaning up */ HOLD_INTERRUPTS(); /* Commit updates to the relation map --- do this as late as possible */ AtEOXact_RelationMap(true); /* * set the current transaction state information appropriately during * commit processing */ s->state = TRANS_COMMIT; /* * Here is where we really truly commit. */ latestXid = RecordTransactionCommit(); TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->lxid); /* * Let others know about no transaction in progress by me. Note that this * must be done _before_ releasing locks we hold and _after_ * RecordTransactionCommit. */ ProcArrayEndTransaction(MyProc, latestXid); /* * 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. * * Resources that can be associated with individual queries are handled by * the ResourceOwner mechanism. The other calls here are for backend-wide * state. */ CallXactCallbacks(XACT_EVENT_COMMIT); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, true, true); /* Check we've released all buffer pins */ AtEOXact_Buffers(true); /* Clean up the relation cache */ AtEOXact_RelationCache(true); /* * Make catalog changes visible to all backends. This has to happen after * relcache references are dropped (see comments for * AtEOXact_RelationCache), but before locks are released (if anyone is * waiting for lock on a relation we've modified, we want them to know * about the catalog change before they start using the relation). */ AtEOXact_Inval(true); AtEOXact_MultiXact(); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_LOCKS, true, true); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_AFTER_LOCKS, true, true); /* * Likewise, dropping of files deleted during the transaction is best done * after releasing relcache and buffer pins. (This is not strictly * necessary during commit, since such pins should have been released * already, but this ordering is definitely critical during abort.) Since * this may take many seconds, also delay until after releasing locks. * Other backends will observe the attendant catalog changes and not * attempt to access affected files. */ smgrDoPendingDeletes(true); /* Check we've released all catcache entries */ AtEOXact_CatCache(true); AtCommit_Notify(); AtEOXact_GUC(true, 1); AtEOXact_SPI(true); AtEOXact_on_commit_actions(true); AtEOXact_Namespace(true); AtEOXact_SMgr(); AtEOXact_Files(); AtEOXact_ComboCid(); AtEOXact_HashTables(true); AtEOXact_PgStat(true); AtEOXact_Snapshot(true); pgstat_report_xact_timestamp(0); CurrentResourceOwner = NULL; ResourceOwnerDelete(TopTransactionResourceOwner); s->curTransactionOwner = NULL; CurTransactionResourceOwner = NULL; TopTransactionResourceOwner = NULL; AtCommit_Memory(); s->transactionId = InvalidTransactionId; s->subTransactionId = InvalidSubTransactionId; s->nestingLevel = 0; s->gucNestLevel = 0; s->childXids = NULL; s->nChildXids = 0; s->maxChildXids = 0; /* * done with commit processing, set current transaction state back to * default */ s->state = TRANS_DEFAULT; RESUME_INTERRUPTS(); }
void CommitTransactionCommand | ( | void | ) |
Definition at line 2508 of file xact.c.
References AbortSubTransaction(), AbortTransaction(), Assert, AssertState, TransactionStateData::blockState, BlockStateAsString(), CleanupSubTransaction(), CleanupTransaction(), CommandCounterIncrement(), CommitSubTransaction(), CommitTransaction(), CommitTransactionCommand(), DefineSavepoint(), elog, ERROR, FATAL, TransactionStateData::name, name, NULL, TransactionStateData::parent, PrepareTransaction(), TransactionStateData::savepointLevel, StartSubTransaction(), TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by BeginInternalSubTransaction(), cluster(), CommitTransactionCommand(), DefineIndex(), do_autovacuum(), finish_xact_command(), get_database_list(), index_drop(), initialize_worker_spi(), InitPostgres(), movedb(), ProcessCatchupEvent(), ProcessCompletedNotifies(), ProcessIncomingNotify(), ReindexDatabase(), RemoveTempRelationsCallback(), vacuum(), vacuum_rel(), and worker_spi_main().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { /* * This shouldn't happen, because it means the previous * StartTransactionCommand didn't set the STARTED state * appropriately. */ case TBLOCK_DEFAULT: elog(FATAL, "CommitTransactionCommand: unexpected state %s", BlockStateAsString(s->blockState)); break; /* * If we aren't in a transaction block, just do our usual * transaction commit, and return to the idle state. */ case TBLOCK_STARTED: CommitTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * We are completing a "BEGIN TRANSACTION" command, so we change * to the "transaction block in progress" state and return. (We * assume the BEGIN did nothing to the database, so we need no * CommandCounterIncrement.) */ 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: case TBLOCK_SUBINPROGRESS: CommandCounterIncrement(); break; /* * We are completing a "COMMIT" command. Do it and return to the * idle 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 a ROLLBACK comand. */ case TBLOCK_ABORT: case TBLOCK_SUBABORT: break; /* * Here we were in an aborted transaction block and we just got * the ROLLBACK command from the user, so clean up the * already-aborted transaction and return to the idle state. */ case TBLOCK_ABORT_END: CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * Here we were in a perfectly good transaction block but the user * told us to ROLLBACK anyway. We have to abort the transaction * and then clean up. */ case TBLOCK_ABORT_PENDING: AbortTransaction(); CleanupTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * We are completing a "PREPARE TRANSACTION" command. Do it and * return to the idle state. */ case TBLOCK_PREPARE: PrepareTransaction(); s->blockState = TBLOCK_DEFAULT; break; /* * We were just issued a SAVEPOINT inside a transaction block. * Start a subtransaction. (DefineSavepoint already did * PushTransaction, so as to have someplace to put the SUBBEGIN * state.) */ case TBLOCK_SUBBEGIN: StartSubTransaction(); s->blockState = TBLOCK_SUBINPROGRESS; break; /* * We were issued a RELEASE command, so we end the current * subtransaction and return to the parent transaction. The parent * might be ended too, so repeat till we find an INPROGRESS * transaction or subtransaction. */ case TBLOCK_SUBRELEASE: do { CommitSubTransaction(); s = CurrentTransactionState; /* changed by pop */ } while (s->blockState == TBLOCK_SUBRELEASE); Assert(s->blockState == TBLOCK_INPROGRESS || s->blockState == TBLOCK_SUBINPROGRESS); break; /* * We were issued a COMMIT, so we end the current subtransaction * hierarchy and perform final commit. We do this by rolling up * any subtransactions into their parent, which leads to O(N^2) * operations with respect to resource owners - this isn't that * bad until we approach a thousands of savepoints but is * necessary for correctness should after triggers create new * resource owners. */ case TBLOCK_SUBCOMMIT: do { CommitSubTransaction(); s = CurrentTransactionState; /* changed by pop */ } while (s->blockState == TBLOCK_SUBCOMMIT); /* If we had a COMMIT command, finish off the main xact too */ if (s->blockState == TBLOCK_END) { Assert(s->parent == NULL); CommitTransaction(); s->blockState = TBLOCK_DEFAULT; } else if (s->blockState == TBLOCK_PREPARE) { Assert(s->parent == NULL); PrepareTransaction(); s->blockState = TBLOCK_DEFAULT; } else elog(ERROR, "CommitTransactionCommand: unexpected state %s", BlockStateAsString(s->blockState)); break; /* * The current already-failed subtransaction is ending due to a * ROLLBACK or ROLLBACK TO command, so pop it and recursively * examine the parent (which could be in any of several states). */ case TBLOCK_SUBABORT_END: CleanupSubTransaction(); CommitTransactionCommand(); break; /* * As above, but it's not dead yet, so abort first. */ case TBLOCK_SUBABORT_PENDING: AbortSubTransaction(); CleanupSubTransaction(); CommitTransactionCommand(); break; /* * The current subtransaction is the target of a ROLLBACK TO * command. Abort and pop it, then start a new subtransaction * with the same name. */ case TBLOCK_SUBRESTART: { char *name; int savepointLevel; /* save name and keep Cleanup from freeing it */ name = s->name; s->name = NULL; savepointLevel = s->savepointLevel; AbortSubTransaction(); CleanupSubTransaction(); DefineSavepoint(NULL); s = CurrentTransactionState; /* changed by push */ s->name = name; s->savepointLevel = savepointLevel; /* This is the same as TBLOCK_SUBBEGIN case */ AssertState(s->blockState == TBLOCK_SUBBEGIN); StartSubTransaction(); s->blockState = TBLOCK_SUBINPROGRESS; } break; /* * Same as above, but the subtransaction had already failed, so we * don't need AbortSubTransaction. */ case TBLOCK_SUBABORT_RESTART: { char *name; int savepointLevel; /* save name and keep Cleanup from freeing it */ name = s->name; s->name = NULL; savepointLevel = s->savepointLevel; CleanupSubTransaction(); DefineSavepoint(NULL); s = CurrentTransactionState; /* changed by push */ s->name = name; s->savepointLevel = savepointLevel; /* This is the same as TBLOCK_SUBBEGIN case */ AssertState(s->blockState == TBLOCK_SUBBEGIN); StartSubTransaction(); s->blockState = TBLOCK_SUBINPROGRESS; } break; } }
void DefineSavepoint | ( | char * | name | ) |
Definition at line 3464 of file xact.c.
References TransactionStateData::blockState, BlockStateAsString(), elog, FATAL, MemoryContextStrdup(), TransactionStateData::name, PushTransaction(), TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, TBLOCK_SUBRESTART, and TopTransactionContext.
Referenced by CommitTransactionCommand(), and standard_ProcessUtility().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: /* Normal subtransaction start */ PushTransaction(); s = CurrentTransactionState; /* changed by push */ /* * Savepoint names, like the TransactionState block itself, live * in TopTransactionContext. */ if (name) s->name = MemoryContextStrdup(TopTransactionContext, name); break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_STARTED: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT: case TBLOCK_SUBABORT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "DefineSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; } }
bool EndTransactionBlock | ( | void | ) |
Definition at line 3261 of file xact.c.
References TransactionStateData::blockState, BlockStateAsString(), elog, ereport, errcode(), errmsg(), FATAL, NULL, TransactionStateData::parent, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, TBLOCK_SUBRESTART, and WARNING.
Referenced by PrepareTransactionBlock(), and standard_ProcessUtility().
{ TransactionState s = CurrentTransactionState; bool result = false; switch (s->blockState) { /* * We are in a transaction block, so tell CommitTransactionCommand * to COMMIT. */ case TBLOCK_INPROGRESS: s->blockState = TBLOCK_END; result = true; break; /* * We are in a failed transaction block. Tell * CommitTransactionCommand it's time to exit the block. */ case TBLOCK_ABORT: s->blockState = TBLOCK_ABORT_END; break; /* * We are in a live subtransaction block. Set up to subcommit all * open subtransactions and then commit the main transaction. */ case TBLOCK_SUBINPROGRESS: while (s->parent != NULL) { if (s->blockState == TBLOCK_SUBINPROGRESS) s->blockState = TBLOCK_SUBCOMMIT; else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); s = s->parent; } if (s->blockState == TBLOCK_INPROGRESS) s->blockState = TBLOCK_END; else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); result = true; break; /* * Here we are inside an aborted subtransaction. Treat the COMMIT * as ROLLBACK: set up to abort everything and exit the main * transaction. */ case TBLOCK_SUBABORT: while (s->parent != NULL) { if (s->blockState == TBLOCK_SUBINPROGRESS) s->blockState = TBLOCK_SUBABORT_PENDING; else if (s->blockState == TBLOCK_SUBABORT) s->blockState = TBLOCK_SUBABORT_END; else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); s = s->parent; } if (s->blockState == TBLOCK_INPROGRESS) s->blockState = TBLOCK_ABORT_PENDING; else if (s->blockState == TBLOCK_ABORT) s->blockState = TBLOCK_ABORT_END; else elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; /* * The user issued COMMIT when not inside a transaction. Issue a * WARNING, staying in TBLOCK_STARTED state. The upcoming call to * CommitTransactionCommand() will then close the transaction and * put us back into the default state. */ case TBLOCK_STARTED: ereport(WARNING, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), errmsg("there is no transaction in progress"))); result = true; break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "EndTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; } return result; }
void ForceSyncCommit | ( | void | ) |
Definition at line 798 of file xact.c.
References forceSyncCommit.
Referenced by createdb(), CreateTableSpace(), dropdb(), DropTableSpace(), and movedb().
{ forceSyncCommit = true; }
Definition at line 604 of file xact.c.
References currentCommandId, and currentCommandIdUsed.
Referenced by ATRewriteTable(), CopyFrom(), GetSnapshotData(), HeapTupleSatisfiesNow(), intorel_startup(), pgrowlocks(), RegisterRelcacheInvalidation(), simple_heap_delete(), simple_heap_insert(), simple_heap_update(), standard_ExecutorStart(), toast_save_datum(), transientrel_startup(), and UpdateActiveSnapshotCommandId().
{ /* this is global to a transaction, not subtransaction-local */ if (used) currentCommandIdUsed = true; return currentCommandId; }
TimestampTz GetCurrentStatementStartTimestamp | ( | void | ) |
Definition at line 625 of file xact.c.
References stmtStartTimestamp.
Referenced by check_log_duration(), CreatePortal(), pgstat_report_activity(), statement_timestamp(), and StorePreparedStatement().
{ return stmtStartTimestamp; }
SubTransactionId GetCurrentSubTransactionId | ( | void | ) |
Definition at line 566 of file xact.c.
References TransactionStateData::subTransactionId.
Referenced by AllocateDir(), AllocateFile(), CopyFrom(), CreatePortal(), ExecuteTruncate(), init_sql_fcache(), InitTempTableNamespace(), inv_open(), OpenPipeStream(), OpenTransientFile(), plpgsql_create_econtext(), register_on_commit_action(), RelationBuildLocalRelation(), RelationSetNewRelfilenode(), remove_on_commit_action(), sepgsql_set_client_label(), and SPI_connect().
{ TransactionState s = CurrentTransactionState; return s->subTransactionId; }
TransactionId GetCurrentTransactionId | ( | void | ) |
Definition at line 371 of file xact.c.
References AssignTransactionId(), TransactionStateData::transactionId, and TransactionIdIsValid.
Referenced by AlterEnum(), asyncQueueNotificationToEntry(), funny_dup17(), heap_delete(), heap_insert(), heap_lock_tuple(), heap_multi_insert(), heap_update(), PreCommit_Notify(), PrepareTransaction(), and vac_truncate_clog().
{ TransactionState s = CurrentTransactionState; if (!TransactionIdIsValid(s->transactionId)) AssignTransactionId(s); return s->transactionId; }
TransactionId GetCurrentTransactionIdIfAny | ( | void | ) |
Definition at line 388 of file xact.c.
References TransactionStateData::transactionId.
Referenced by pgrowlocks(), RecordTransactionAbort(), and XLogInsert().
{ return CurrentTransactionState->transactionId; }
int GetCurrentTransactionNestLevel | ( | void | ) |
Definition at line 669 of file xact.c.
References TransactionStateData::nestingLevel.
Referenced by AfterTriggerBeginSubXact(), AfterTriggerEndSubXact(), AfterTriggerSetState(), AtEOSubXact_Inval(), AtEOSubXact_Namespace(), AtStart_Inval(), AtSubAbort_Notify(), AtSubCommit_Notify(), AtSubCommit_smgr(), AtSubStart_Inval(), AtSubStart_Notify(), begin_remote_xact(), pgfdw_subxact_callback(), pgstat_count_heap_delete(), pgstat_count_heap_insert(), pgstat_count_heap_update(), PopOverrideSearchPath(), PushActiveSnapshot(), PushOverrideSearchPath(), register_seq_scan(), RelationCreateStorage(), RelationDropStorage(), RelationMapUpdateMap(), smgrDoPendingDeletes(), and smgrGetPendingDeletes().
{ TransactionState s = CurrentTransactionState; return s->nestingLevel; }
TimestampTz GetCurrentTransactionStartTimestamp | ( | void | ) |
Definition at line 616 of file xact.c.
References xactStartTimestamp.
Referenced by GetCurrentDateTime(), GetCurrentTimeUsec(), now(), and pg_timezone_names().
{ return xactStartTimestamp; }
TimestampTz GetCurrentTransactionStopTimestamp | ( | void | ) |
Definition at line 637 of file xact.c.
References GetCurrentTimestamp(), and xactStopTimestamp.
Referenced by pgstat_report_stat().
{ if (xactStopTimestamp != 0) return xactStopTimestamp; return GetCurrentTimestamp(); }
TransactionId GetStableLatestTransactionId | ( | void | ) |
Definition at line 402 of file xact.c.
References Assert, GetTopTransactionIdIfAny(), PGPROC::lxid, MyProc, ReadNewTransactionId(), and TransactionIdIsValid.
Referenced by xid_age().
{ static LocalTransactionId lxid = InvalidLocalTransactionId; static TransactionId stablexid = InvalidTransactionId; if (lxid != MyProc->lxid) { lxid = MyProc->lxid; stablexid = GetTopTransactionIdIfAny(); if (!TransactionIdIsValid(stablexid)) stablexid = ReadNewTransactionId(); } Assert(TransactionIdIsValid(stablexid)); return stablexid; }
TransactionId GetTopTransactionId | ( | void | ) |
Definition at line 343 of file xact.c.
References AssignTransactionId(), TransactionStateData::transactionId, and TransactionIdIsValid.
Referenced by AssignTransactionId(), AtEOXact_Snapshot(), ExportSnapshot(), LockGXact(), LogAccessExclusiveLock(), LogAccessExclusiveLockPrepare(), and txid_current().
TransactionId GetTopTransactionIdIfAny | ( | void | ) |
Definition at line 358 of file xact.c.
References TransactionStateData::transactionId.
Referenced by CheckForSerializableConflictOut(), ConditionalXactLockTableWait(), GetSerializableTransactionSnapshotInt(), GetStableLatestTransactionId(), ImportSnapshot(), index_drop(), index_set_state_flags(), initSpGistState(), log_line_prefix(), PredicateLockTuple(), RecordTransactionCommit(), write_csvlog(), XactLockTableWait(), and XidIsConcurrent().
{ return TopTransactionStateData.transactionId; }
bool IsAbortedTransactionBlockState | ( | void | ) |
Definition at line 324 of file xact.c.
References TransactionStateData::blockState, TBLOCK_ABORT, and TBLOCK_SUBABORT.
Referenced by errdetail_params(), exec_bind_message(), exec_describe_portal_message(), exec_describe_statement_message(), exec_execute_message(), exec_parse_message(), exec_simple_query(), HandleFunctionRequest(), PostgresMain(), and RecoveryConflictInterrupt().
{ TransactionState s = CurrentTransactionState; if (s->blockState == TBLOCK_ABORT || s->blockState == TBLOCK_SUBABORT) return true; return false; }
Definition at line 3007 of file xact.c.
References TransactionStateData::blockState, IsSubTransaction(), IsTransactionBlock(), TBLOCK_DEFAULT, and TBLOCK_STARTED.
Referenced by vacuum().
{ /* * Return true on same conditions that would make PreventTransactionChain * error out */ if (IsTransactionBlock()) return true; if (IsSubTransaction()) return true; if (!isTopLevel) return true; if (CurrentTransactionState->blockState != TBLOCK_DEFAULT && CurrentTransactionState->blockState != TBLOCK_STARTED) return true; return false; }
bool IsSubTransaction | ( | void | ) |
Definition at line 4014 of file xact.c.
References TransactionStateData::nestingLevel.
Referenced by AfterTriggerSetState(), check_transaction_deferrable(), check_transaction_read_only(), check_XactIsoLevel(), CheckTargetForConflictsIn(), ExportSnapshot(), ImportSnapshot(), IsInTransactionChain(), PreventTransactionChain(), RecoveryConflictInterrupt(), and RequireTransactionChain().
{ TransactionState s = CurrentTransactionState; if (s->nestingLevel >= 2) return true; return false; }
bool IsTransactionBlock | ( | void | ) |
Definition at line 3943 of file xact.c.
References TransactionStateData::blockState, TBLOCK_DEFAULT, and TBLOCK_STARTED.
Referenced by IsInTransactionChain(), PreventTransactionChain(), and RequireTransactionChain().
{ TransactionState s = CurrentTransactionState; if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED) return false; return true; }
bool IsTransactionOrTransactionBlock | ( | void | ) |
Definition at line 3961 of file xact.c.
References TransactionStateData::blockState, and TBLOCK_DEFAULT.
Referenced by EnableNotifyInterrupt(), PostgresMain(), ProcessCatchupEvent(), and RecoveryConflictInterrupt().
{ TransactionState s = CurrentTransactionState; if (s->blockState == TBLOCK_DEFAULT) return false; return true; }
bool IsTransactionState | ( | void | ) |
Definition at line 304 of file xact.c.
References TransactionStateData::state, and TRANS_INPROGRESS.
Referenced by check_client_encoding(), check_default_tablespace(), check_role(), check_session_authorization(), check_temp_tablespaces(), check_transaction_read_only(), check_TSCurrentConfig(), check_XactIsoLevel(), HandleFunctionRequest(), pg_do_encoding_conversion(), PrepareClientEncoding(), PrepareTempTablespaces(), SetMultiXactIdLimit(), SetTransactionIdLimit(), and SocketBackend().
{ TransactionState s = CurrentTransactionState; /* * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states. However, we * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT, * TRANS_PREPARE since it might be too soon or too late within those * transition states to do anything interesting. Hence, the only "valid" * state is TRANS_INPROGRESS. */ return (s->state == TRANS_INPROGRESS); }
static void PopTransaction | ( | void | ) | [static] |
Definition at line 4380 of file xact.c.
References CurrentResourceOwner, TransactionStateData::curTransactionContext, CurTransactionContext, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, elog, FATAL, MemoryContextSwitchTo(), TransactionStateData::name, NULL, TransactionStateData::parent, pfree(), TransactionStateData::state, TRANS_DEFAULT, TransStateAsString(), and WARNING.
Referenced by CleanupSubTransaction(), and CommitSubTransaction().
{ TransactionState s = CurrentTransactionState; if (s->state != TRANS_DEFAULT) elog(WARNING, "PopTransaction while in %s state", TransStateAsString(s->state)); if (s->parent == NULL) elog(FATAL, "PopTransaction with no parent"); CurrentTransactionState = s->parent; /* Let's just make sure CurTransactionContext is good */ CurTransactionContext = s->parent->curTransactionContext; MemoryContextSwitchTo(CurTransactionContext); /* Ditto for ResourceOwner links */ CurTransactionResourceOwner = s->parent->curTransactionOwner; CurrentResourceOwner = s->parent->curTransactionOwner; /* Free the old child structure */ if (s->name) pfree(s->name); pfree(s); }
static void PrepareTransaction | ( | void | ) | [static] |
Definition at line 2015 of file xact.c.
References AfterTriggerEndXact(), AfterTriggerFireDeferred(), Assert, AtCommit_Memory(), AtEOXact_Buffers(), AtEOXact_CatCache(), AtEOXact_ComboCid(), AtEOXact_Files(), AtEOXact_GUC(), AtEOXact_HashTables(), AtEOXact_LargeObject(), AtEOXact_Namespace(), AtEOXact_on_commit_actions(), AtEOXact_RelationCache(), AtEOXact_SMgr(), AtEOXact_Snapshot(), AtEOXact_SPI(), AtPrepare_Locks(), AtPrepare_MultiXact(), AtPrepare_Notify(), AtPrepare_PgStat(), AtPrepare_PredicateLocks(), AtPrepare_RelationMap(), BufmgrCommit(), CallXactCallbacks(), TransactionStateData::childXids, CurrentResourceOwner, TransactionStateData::curTransactionOwner, CurTransactionResourceOwner, elog, EndPrepare(), ereport, errcode(), errmsg(), ERROR, GetCurrentTimestamp(), GetCurrentTransactionId(), GetUserId(), TransactionStateData::gucNestLevel, HOLD_INTERRUPTS, MarkAsPreparing(), TransactionStateData::maxChildXids, MyDatabaseId, MyProc, MyXactAccessedTempRel, TransactionStateData::nChildXids, TransactionStateData::nestingLevel, NULL, TransactionStateData::parent, PostPrepare_Inval(), PostPrepare_Locks(), PostPrepare_MultiXact(), PostPrepare_PgStat(), PostPrepare_PredicateLocks(), PostPrepare_smgr(), PreCommit_CheckForSerializationFailure(), PreCommit_on_commit_actions(), PreCommit_Portals(), prepareGID, ProcArrayClearTransaction(), RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerDelete(), ResourceOwnerRelease(), RESUME_INTERRUPTS, ShowTransactionState(), StartPrepare(), TransactionStateData::state, TransactionStateData::subTransactionId, TopTransactionResourceOwner, TRANS_INPROGRESS, TransactionStateData::transactionId, TransStateAsString(), WARNING, XACT_EVENT_PRE_PREPARE, XACT_EVENT_PREPARE, XactHasExportedSnapshots(), and XactLastRecEnd.
Referenced by CommitTransactionCommand().
{ TransactionState s = CurrentTransactionState; TransactionId xid = GetCurrentTransactionId(); GlobalTransaction gxact; TimestampTz prepared_at; ShowTransactionState("PrepareTransaction"); /* * check the current transaction state */ if (s->state != TRANS_INPROGRESS) elog(WARNING, "PrepareTransaction while in %s state", TransStateAsString(s->state)); Assert(s->parent == NULL); /* * Do pre-commit processing that involves calling user-defined code, such * as triggers. Since closing cursors could queue trigger actions, * triggers could open cursors, etc, we have to keep looping until there's * nothing left to do. */ for (;;) { /* * Fire all currently pending deferred triggers. */ AfterTriggerFireDeferred(); /* * Close open portals (converting holdable ones into static portals). * If there weren't any, we are done ... otherwise loop back to check * if they queued deferred triggers. Lather, rinse, repeat. */ if (!PreCommit_Portals(true)) break; } CallXactCallbacks(XACT_EVENT_PRE_PREPARE); /* * The remaining actions cannot call any user-defined code, so it's safe * to start shutting down within-transaction services. But note that most * of this stuff could still throw an error, which would switch us into * the transaction-abort path. */ /* Shut down the deferred-trigger manager */ AfterTriggerEndXact(true); /* * Let ON COMMIT management do its thing (must happen after closing * cursors, to avoid dangling-reference problems) */ PreCommit_on_commit_actions(); /* close large objects before lower-level cleanup */ AtEOXact_LargeObject(true); /* * Mark serializable transaction as complete for predicate locking * purposes. This should be done as late as we can put it and still allow * errors to be raised for failure patterns found at commit. */ PreCommit_CheckForSerializationFailure(); /* NOTIFY will be handled below */ /* * Don't allow PREPARE TRANSACTION if we've accessed a temporary table in * this transaction. Having the prepared xact hold locks on another * backend's temp table seems a bad idea --- for instance it would prevent * the backend from exiting. There are other problems too, such as how to * clean up the source backend's local buffers and ON COMMIT state if the * prepared xact includes a DROP of a temp table. * * We must check this after executing any ON COMMIT actions, because they * might still access a temp relation. * * XXX In principle this could be relaxed to allow some useful special * cases, such as a temp table created and dropped all within the * transaction. That seems to require much more bookkeeping though. */ if (MyXactAccessedTempRel) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot PREPARE a transaction that has operated on temporary tables"))); /* * Likewise, don't allow PREPARE after pg_export_snapshot. This could be * supported if we added cleanup logic to twophase.c, but for now it * doesn't seem worth the trouble. */ if (XactHasExportedSnapshots()) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot PREPARE a transaction that has exported snapshots"))); /* Prevent cancel/die interrupt while cleaning up */ HOLD_INTERRUPTS(); /* * set the current transaction state information appropriately during * prepare processing */ s->state = TRANS_PREPARE; prepared_at = GetCurrentTimestamp(); /* Tell bufmgr and smgr to prepare for commit */ BufmgrCommit(); /* * Reserve the GID for this transaction. This could fail if the requested * GID is invalid or already in use. */ gxact = MarkAsPreparing(xid, prepareGID, prepared_at, GetUserId(), MyDatabaseId); prepareGID = NULL; /* * Collect data for the 2PC state file. Note that in general, no actual * state change should happen in the called modules during this step, * since it's still possible to fail before commit, and in that case we * want transaction abort to be able to clean up. (In particular, the * AtPrepare routines may error out if they find cases they cannot * handle.) State cleanup should happen in the PostPrepare routines * below. However, some modules can go ahead and clear state here because * they wouldn't do anything with it during abort anyway. * * Note: because the 2PC state file records will be replayed in the same * order they are made, the order of these calls has to match the order in * which we want things to happen during COMMIT PREPARED or ROLLBACK * PREPARED; in particular, pay attention to whether things should happen * before or after releasing the transaction's locks. */ StartPrepare(gxact); AtPrepare_Notify(); AtPrepare_Locks(); AtPrepare_PredicateLocks(); AtPrepare_PgStat(); AtPrepare_MultiXact(); AtPrepare_RelationMap(); /* * Here is where we really truly prepare. * * We have to record transaction prepares even if we didn't make any * updates, because the transaction manager might get confused if we lose * a global transaction. */ EndPrepare(gxact); /* * Now we clean up backend-internal state and release internal resources. */ /* Reset XactLastRecEnd until the next transaction writes something */ XactLastRecEnd = 0; /* * Let others know about no transaction in progress by me. This has to be * done *after* the prepared transaction has been marked valid, else * someone may think it is unlocked and recyclable. */ ProcArrayClearTransaction(MyProc); /* * This is all post-transaction cleanup. Note that if an error is raised * here, it's too late to abort the transaction. This should be just * noncritical resource releasing. See notes in CommitTransaction. */ CallXactCallbacks(XACT_EVENT_PREPARE); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, true, true); /* Check we've released all buffer pins */ AtEOXact_Buffers(true); /* Clean up the relation cache */ AtEOXact_RelationCache(true); /* notify doesn't need a postprepare call */ PostPrepare_PgStat(); PostPrepare_Inval(); PostPrepare_smgr(); PostPrepare_MultiXact(xid); PostPrepare_Locks(xid); PostPrepare_PredicateLocks(xid); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_LOCKS, true, true); ResourceOwnerRelease(TopTransactionResourceOwner, RESOURCE_RELEASE_AFTER_LOCKS, true, true); /* Check we've released all catcache entries */ AtEOXact_CatCache(true); /* PREPARE acts the same as COMMIT as far as GUC is concerned */ AtEOXact_GUC(true, 1); AtEOXact_SPI(true); AtEOXact_on_commit_actions(true); AtEOXact_Namespace(true); AtEOXact_SMgr(); AtEOXact_Files(); AtEOXact_ComboCid(); AtEOXact_HashTables(true); /* don't call AtEOXact_PgStat here */ AtEOXact_Snapshot(true); CurrentResourceOwner = NULL; ResourceOwnerDelete(TopTransactionResourceOwner); s->curTransactionOwner = NULL; CurTransactionResourceOwner = NULL; TopTransactionResourceOwner = NULL; AtCommit_Memory(); s->transactionId = InvalidTransactionId; s->subTransactionId = InvalidSubTransactionId; s->nestingLevel = 0; s->gucNestLevel = 0; s->childXids = NULL; s->nChildXids = 0; s->maxChildXids = 0; /* * done with 1st phase commit processing, set current transaction state * back to default */ s->state = TRANS_DEFAULT; RESUME_INTERRUPTS(); }
bool PrepareTransactionBlock | ( | char * | gid | ) |
Definition at line 3210 of file xact.c.
References Assert, TransactionStateData::blockState, EndTransactionBlock(), MemoryContextStrdup(), NULL, TransactionStateData::parent, prepareGID, TBLOCK_END, TBLOCK_STARTED, and TopTransactionContext.
Referenced by standard_ProcessUtility().
{ TransactionState s; bool result; /* Set up to commit the current transaction */ result = EndTransactionBlock(); /* If successful, change outer tblock state to PREPARE */ if (result) { s = CurrentTransactionState; while (s->parent != NULL) s = s->parent; if (s->blockState == TBLOCK_END) { /* Save GID where PrepareTransaction can find it again */ prepareGID = MemoryContextStrdup(TopTransactionContext, gid); s->blockState = TBLOCK_PREPARE; } else { /* * ignore case where we are not in a transaction; * EndTransactionBlock already issued a warning. */ Assert(s->blockState == TBLOCK_STARTED); /* Don't send back a PREPARE result tag... */ result = false; } } return result; }
void PreventTransactionChain | ( | bool | isTopLevel, | |
const char * | stmtType | |||
) |
Definition at line 2912 of file xact.c.
References TransactionStateData::blockState, elog, ereport, errcode(), errmsg(), ERROR, FATAL, IsSubTransaction(), IsTransactionBlock(), TBLOCK_DEFAULT, and TBLOCK_STARTED.
Referenced by AlterDatabase(), AlterEnum(), cluster(), DiscardAll(), ExecDropStmt(), ProcessUtilitySlow(), standard_ProcessUtility(), and vacuum().
{ /* * xact block already started? */ if (IsTransactionBlock()) ereport(ERROR, (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), /* translator: %s represents an SQL statement name */ errmsg("%s cannot run inside a transaction block", stmtType))); /* * subtransaction? */ if (IsSubTransaction()) ereport(ERROR, (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), /* translator: %s represents an SQL statement name */ errmsg("%s cannot run inside a subtransaction", stmtType))); /* * inside a function call? */ if (!isTopLevel) ereport(ERROR, (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), /* translator: %s represents an SQL statement name */ errmsg("%s cannot be executed from a function or multi-command string", stmtType))); /* If we got past IsTransactionBlock test, should be in default state */ if (CurrentTransactionState->blockState != TBLOCK_DEFAULT && CurrentTransactionState->blockState != TBLOCK_STARTED) elog(FATAL, "cannot prevent transaction chain"); /* all okay */ }
static void PushTransaction | ( | void | ) | [static] |
Definition at line 4322 of file xact.c.
References TransactionStateData::blockState, currentSubTransactionId, ereport, errcode(), errmsg(), ERROR, GetUserIdAndSecContext(), TransactionStateData::gucNestLevel, InvalidSubTransactionId, MemoryContextAllocZero(), TransactionStateData::nestingLevel, NewGUCNestLevel(), TransactionStateData::parent, pfree(), TransactionStateData::prevSecContext, TransactionStateData::prevUser, TransactionStateData::prevXactReadOnly, TransactionStateData::savepointLevel, TransactionStateData::state, TransactionStateData::subTransactionId, TopTransactionContext, TransactionStateData::transactionId, and XactReadOnly.
Referenced by BeginInternalSubTransaction(), and DefineSavepoint().
{ TransactionState p = CurrentTransactionState; TransactionState s; /* * We keep subtransaction state nodes in TopTransactionContext. */ s = (TransactionState) MemoryContextAllocZero(TopTransactionContext, sizeof(TransactionStateData)); /* * Assign a subtransaction ID, watching out for counter wraparound. */ currentSubTransactionId += 1; if (currentSubTransactionId == InvalidSubTransactionId) { currentSubTransactionId -= 1; pfree(s); ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("cannot have more than 2^32-1 subtransactions in a transaction"))); } /* * We can now stack a minimally valid subtransaction without fear of * failure. */ s->transactionId = InvalidTransactionId; /* until assigned */ s->subTransactionId = currentSubTransactionId; s->parent = p; s->nestingLevel = p->nestingLevel + 1; s->gucNestLevel = NewGUCNestLevel(); s->savepointLevel = p->savepointLevel; s->state = TRANS_DEFAULT; s->blockState = TBLOCK_SUBBEGIN; GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext); s->prevXactReadOnly = XactReadOnly; CurrentTransactionState = s; /* * AbortSubTransaction and CleanupSubTransaction have to be able to cope * with the subtransaction from here on out; in particular they should not * assume that it necessarily has a transaction context, resource owner, * or XID. */ }
static TransactionId RecordTransactionAbort | ( | bool | isSubXact | ) | [static] |
Definition at line 1381 of file xact.c.
References XLogRecData::buffer, XLogRecData::data, elog, END_CRIT_SECTION, GetCurrentTimestamp(), GetCurrentTransactionIdIfAny(), XLogRecData::len, XLogRecData::next, xl_xact_abort::nrels, xl_xact_abort::nsubxacts, PANIC, pfree(), SetCurrentTransactionStopTimestamp(), smgrGetPendingDeletes(), START_CRIT_SECTION, TransactionIdAbortTree(), TransactionIdDidCommit(), TransactionIdIsValid, TransactionIdLatest(), xl_xact_abort::xact_time, xactGetCommittedChildren(), XactLastRecEnd, xactStopTimestamp, XidCacheRemoveRunningXids(), XLOG_XACT_ABORT, XLogInsert(), and XLogSetAsyncXactLSN().
Referenced by AbortSubTransaction(), and AbortTransaction().
{ 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 = 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); 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); /* * Report the latest async abort LSN, so that the WAL writer knows to * flush this abort. There's nothing to be gained by delaying this, since * WALWriter may as well do this when it can. This is important with * streaming replication because if we don't flush WAL regularly we will * find that large aborts leave us with a long backlog for when commits * occur after the abort, increasing our window of data loss should * problems occur at that point. */ if (!isSubXact) XLogSetAsyncXactLSN(XactLastRecEnd); /* * 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. */ TransactionIdAbortTree(xid, 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 = 0; /* And clean up local data */ if (rels) pfree(rels); return latestXid; }
static TransactionId RecordTransactionCommit | ( | void | ) | [static] |
Definition at line 955 of file xact.c.
References Assert, XLogRecData::buffer, BufmgrCommit(), cleanup(), XLogRecData::data, xl_xact_commit::dbId, PGXACT::delayChkpt, elog, END_CRIT_SECTION, ERROR, forceSyncCommit, GetTopTransactionIdIfAny(), XLogRecData::len, MyDatabaseId, MyDatabaseTableSpace, MyPgXact, XLogRecData::next, xl_xact_commit::nmsgs, xl_xact_commit::nrels, xl_xact_commit_compact::nsubxacts, xl_xact_commit::nsubxacts, pfree(), SetCurrentTransactionStopTimestamp(), smgrGetPendingDeletes(), START_CRIT_SECTION, synchronous_commit, SYNCHRONOUS_COMMIT_OFF, SyncRepWaitForLSN(), TransactionIdAsyncCommitTree(), TransactionIdCommitTree(), TransactionIdIsValid, TransactionIdLatest(), xl_xact_commit::tsId, xl_xact_commit_compact::xact_time, xl_xact_commit::xact_time, xactGetCommittedChildren(), xactGetCommittedInvalidationMessages(), XactLastRecEnd, xactStopTimestamp, xl_xact_commit::xinfo, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_COMPACT, XLogFlush(), XLogInsert(), XLogSetAsyncXactLSN(), and XLogStandbyInfoActive.
Referenced by CommitTransaction().
{ TransactionId xid = GetTopTransactionIdIfAny(); bool markXidCommitted = TransactionIdIsValid(xid); TransactionId latestXid = InvalidTransactionId; int nrels; RelFileNode *rels; int nchildren; TransactionId *children; int nmsgs = 0; SharedInvalidationMessage *invalMessages = NULL; bool RelcacheInitFileInval = false; bool wrote_xlog; /* Get data needed for commit record */ nrels = smgrGetPendingDeletes(true, &rels); nchildren = xactGetCommittedChildren(&children); if (XLogStandbyInfoActive()) nmsgs = xactGetCommittedInvalidationMessages(&invalMessages, &RelcacheInitFileInval); wrote_xlog = (XactLastRecEnd != 0); /* * If we haven't been assigned an XID yet, we neither can, nor do we want * to write a COMMIT record. */ if (!markXidCommitted) { /* * We expect that every smgrscheduleunlink is followed by a catalog * update, and hence XID assignment, so we shouldn't get here with any * pending deletes. Use a real test not just an Assert to check this, * since it's a bit fragile. */ if (nrels != 0) elog(ERROR, "cannot commit a transaction that deleted files but has no xid"); /* Can't have child XIDs either; AssignTransactionId enforces this */ Assert(nchildren == 0); /* * If we didn't create XLOG entries, we're done here; otherwise we * should flush those entries the same as a commit record. (An * example of a possible record that wouldn't cause an XID to be * assigned is a sequence advance record due to nextval() --- we want * to flush that to disk before reporting commit.) */ if (!wrote_xlog) goto cleanup; } else { /* * Begin commit critical section and insert the commit XLOG record. */ /* Tell bufmgr and smgr to prepare for commit */ BufmgrCommit(); /* * Mark ourselves as within our "commit critical section". This * forces any concurrent checkpoint to wait until we've updated * pg_clog. Without this, it is possible for the checkpoint to set * REDO after the XLOG record but fail to flush the pg_clog update to * disk, leading to loss of the transaction commit if the system * crashes a little later. * * Note: we could, but don't bother to, set this flag in * RecordTransactionAbort. That's because loss of a transaction abort * is noncritical; the presumption would be that it aborted, anyway. * * It's safe to change the delayChkpt flag of our own backend without * holding the ProcArrayLock, since we're the only one modifying it. * This makes checkpoint's determination of which xacts are delayChkpt a * bit fuzzy, but it doesn't matter. */ START_CRIT_SECTION(); MyPgXact->delayChkpt = true; SetCurrentTransactionStopTimestamp(); /* * Do we need the long commit record? If not, use the compact format. */ if (nrels > 0 || nmsgs > 0 || RelcacheInitFileInval || forceSyncCommit) { XLogRecData rdata[4]; int lastrdata = 0; xl_xact_commit xlrec; /* * Set flags required for recovery processing of commits. */ xlrec.xinfo = 0; if (RelcacheInitFileInval) xlrec.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE; if (forceSyncCommit) xlrec.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT; xlrec.dbId = MyDatabaseId; xlrec.tsId = MyDatabaseTableSpace; xlrec.xact_time = xactStopTimestamp; xlrec.nrels = nrels; xlrec.nsubxacts = nchildren; xlrec.nmsgs = nmsgs; rdata[0].data = (char *) (&xlrec); rdata[0].len = MinSizeOfXactCommit; 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; } /* dump shared cache invalidation messages */ if (nmsgs > 0) { rdata[lastrdata].next = &(rdata[3]); rdata[3].data = (char *) invalMessages; rdata[3].len = nmsgs * sizeof(SharedInvalidationMessage); rdata[3].buffer = InvalidBuffer; lastrdata = 3; } rdata[lastrdata].next = NULL; (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT, rdata); } else { XLogRecData rdata[2]; int lastrdata = 0; xl_xact_commit_compact xlrec; xlrec.xact_time = xactStopTimestamp; xlrec.nsubxacts = nchildren; rdata[0].data = (char *) (&xlrec); rdata[0].len = MinSizeOfXactCommitCompact; rdata[0].buffer = InvalidBuffer; /* dump committed child Xids */ if (nchildren > 0) { rdata[0].next = &(rdata[1]); rdata[1].data = (char *) children; rdata[1].len = nchildren * sizeof(TransactionId); rdata[1].buffer = InvalidBuffer; lastrdata = 1; } rdata[lastrdata].next = NULL; (void) XLogInsert(RM_XACT_ID, XLOG_XACT_COMMIT_COMPACT, rdata); } } /* * Check if we want to commit asynchronously. We can allow the XLOG flush * to happen asynchronously if synchronous_commit=off, or if the current * transaction has not performed any WAL-logged operation. The latter * case can arise if the current transaction wrote only to temporary * and/or unlogged tables. In case of a crash, the loss of such a * transaction will be irrelevant since temp tables will be lost anyway, * and unlogged tables will be truncated. (Given the foregoing, you might * think that it would be unnecessary to emit the XLOG record at all in * this case, but we don't currently try to do that. It would certainly * cause problems at least in Hot Standby mode, where the * KnownAssignedXids machinery requires tracking every XID assignment. It * might be OK to skip it only when wal_level < hot_standby, but for now * we don't.) * * However, if we're doing cleanup of any non-temp rels or committing any * command that wanted to force sync commit, then we must flush XLOG * immediately. (We must not allow asynchronous commit if there are any * non-temp tables to be deleted, because we might delete the files before * the COMMIT record is flushed to disk. We do allow asynchronous commit * if all to-be-deleted tables are temporary though, since they are lost * anyway if we crash.) */ if ((wrote_xlog && synchronous_commit > SYNCHRONOUS_COMMIT_OFF) || forceSyncCommit || nrels > 0) { XLogFlush(XactLastRecEnd); /* * Now we may update the CLOG, if we wrote a COMMIT record above */ if (markXidCommitted) TransactionIdCommitTree(xid, nchildren, children); } else { /* * Asynchronous commit case: * * This enables possible committed transaction loss in the case of a * postmaster crash because WAL buffers are left unwritten. Ideally we * could issue the WAL write without the fsync, but some * wal_sync_methods do not allow separate write/fsync. * * Report the latest async commit LSN, so that the WAL writer knows to * flush this commit. */ XLogSetAsyncXactLSN(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) TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd); } /* * If we entered a commit critical section, leave it now, and let * checkpoints proceed. */ if (markXidCommitted) { MyPgXact->delayChkpt = false; END_CRIT_SECTION(); } /* Compute latestXid while we have the child XIDs handy */ latestXid = TransactionIdLatest(xid, nchildren, children); /* * Wait for synchronous replication, if required. * * Note that at this stage we have marked clog, but still show as running * in the procarray and continue to hold locks. */ if (wrote_xlog) SyncRepWaitForLSN(XactLastRecEnd); /* Reset XactLastRecEnd until the next transaction writes something */ XactLastRecEnd = 0; cleanup: /* Clean up local data */ if (rels) pfree(rels); return latestXid; }
void RegisterSubXactCallback | ( | SubXactCallback | callback, | |
void * | arg | |||
) |
Definition at line 3097 of file xact.c.
References SubXactCallbackItem::arg, SubXactCallbackItem::callback, MemoryContextAlloc(), SubXactCallbackItem::next, and TopMemoryContext.
Referenced by _PG_init(), GetConnection(), and sepgsql_init_client_label().
{ SubXactCallbackItem *item; item = (SubXactCallbackItem *) MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem)); item->callback = callback; item->arg = arg; item->next = SubXact_callbacks; SubXact_callbacks = item; }
void RegisterXactCallback | ( | XactCallback | callback, | |
void * | arg | |||
) |
Definition at line 3042 of file xact.c.
References XactCallbackItem::arg, XactCallbackItem::callback, MemoryContextAlloc(), XactCallbackItem::next, and TopMemoryContext.
Referenced by _PG_init(), GetConnection(), and sepgsql_init_client_label().
{ XactCallbackItem *item; item = (XactCallbackItem *) MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem)); item->callback = callback; item->arg = arg; item->next = Xact_callbacks; Xact_callbacks = item; }
void ReleaseCurrentSubTransaction | ( | void | ) |
Definition at line 3784 of file xact.c.
References Assert, TransactionStateData::blockState, BlockStateAsString(), CommitSubTransaction(), CurTransactionContext, elog, ERROR, MemoryContextSwitchTo(), TransactionStateData::state, TBLOCK_SUBINPROGRESS, and TRANS_INPROGRESS.
Referenced by exec_stmt_block(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), pltcl_subtrans_commit(), PLy_spi_subtransaction_commit(), and PLy_subtransaction_exit().
{ TransactionState s = CurrentTransactionState; if (s->blockState != TBLOCK_SUBINPROGRESS) elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s", BlockStateAsString(s->blockState)); Assert(s->state == TRANS_INPROGRESS); MemoryContextSwitchTo(CurTransactionContext); CommitSubTransaction(); s = CurrentTransactionState; /* changed by pop */ Assert(s->state == TRANS_INPROGRESS); }
void ReleaseSavepoint | ( | List * | options | ) |
Definition at line 3514 of file xact.c.
References DefElem::arg, Assert, TransactionStateData::blockState, BlockStateAsString(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, FATAL, lfirst, TransactionStateData::name, name, TransactionStateData::parent, PointerIsValid, TransactionStateData::savepointLevel, strVal, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by standard_ProcessUtility().
{ TransactionState s = CurrentTransactionState; TransactionState target, xact; ListCell *cell; char *name = NULL; switch (s->blockState) { /* * We can't rollback to a savepoint if there is no savepoint * defined. */ case TBLOCK_INPROGRESS: ereport(ERROR, (errcode(ERRCODE_S_E_INVALID_SPECIFICATION), errmsg("no such savepoint"))); break; /* * We are in a non-aborted subtransaction. This is the only valid * case. */ case TBLOCK_SUBINPROGRESS: break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_STARTED: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT: case TBLOCK_SUBABORT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "ReleaseSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; } foreach(cell, options) { DefElem *elem = lfirst(cell); if (strcmp(elem->defname, "savepoint_name") == 0) name = strVal(elem->arg); } Assert(PointerIsValid(name)); for (target = s; PointerIsValid(target); target = target->parent) { if (PointerIsValid(target->name) && strcmp(target->name, name) == 0) break; } if (!PointerIsValid(target)) ereport(ERROR, (errcode(ERRCODE_S_E_INVALID_SPECIFICATION), errmsg("no such savepoint"))); /* disallow crossing savepoint level boundaries */ if (target->savepointLevel != s->savepointLevel) ereport(ERROR, (errcode(ERRCODE_S_E_INVALID_SPECIFICATION), errmsg("no such savepoint"))); /* * Mark "commit pending" all subtransactions up to the target * subtransaction. The actual commits will happen when control gets to * CommitTransactionCommand. */ xact = CurrentTransactionState; for (;;) { Assert(xact->blockState == TBLOCK_SUBINPROGRESS); xact->blockState = TBLOCK_SUBRELEASE; if (xact == target) break; xact = xact->parent; Assert(PointerIsValid(xact)); } }
void RequireTransactionChain | ( | bool | isTopLevel, | |
const char * | stmtType | |||
) |
Definition at line 2969 of file xact.c.
References ereport, errcode(), errmsg(), ERROR, IsSubTransaction(), and IsTransactionBlock().
Referenced by PerformCursorOpen(), and standard_ProcessUtility().
{ /* * xact block already started? */ if (IsTransactionBlock()) return; /* * subtransaction? */ if (IsSubTransaction()) return; /* * inside a function call? */ if (!isTopLevel) return; ereport(ERROR, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), /* translator: %s represents an SQL statement name */ errmsg("%s can only be used in transaction blocks", stmtType))); }
void RollbackAndReleaseCurrentSubTransaction | ( | void | ) |
Definition at line 3806 of file xact.c.
References AbortSubTransaction(), AssertState, TransactionStateData::blockState, BlockStateAsString(), CleanupSubTransaction(), elog, FATAL, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by exec_stmt_block(), plperl_spi_exec(), plperl_spi_exec_prepared(), plperl_spi_fetchrow(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), pltcl_subtrans_abort(), PLy_abort_open_subtransactions(), PLy_spi_subtransaction_abort(), and PLy_subtransaction_exit().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { /* Must be in a subtransaction */ case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBABORT: break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_STARTED: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_INPROGRESS: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s", BlockStateAsString(s->blockState)); break; } /* * Abort the current subtransaction, if needed. */ if (s->blockState == TBLOCK_SUBINPROGRESS) AbortSubTransaction(); /* And clean it up, too */ CleanupSubTransaction(); s = CurrentTransactionState; /* changed by pop */ AssertState(s->blockState == TBLOCK_SUBINPROGRESS || s->blockState == TBLOCK_INPROGRESS || s->blockState == TBLOCK_STARTED); }
void RollbackToSavepoint | ( | List * | options | ) |
Definition at line 3614 of file xact.c.
References DefElem::arg, Assert, TransactionStateData::blockState, BlockStateAsString(), DefElem::defname, elog, ereport, errcode(), errmsg(), ERROR, FATAL, lfirst, TransactionStateData::name, name, TransactionStateData::parent, PointerIsValid, TransactionStateData::savepointLevel, strVal, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by standard_ProcessUtility().
{ TransactionState s = CurrentTransactionState; TransactionState target, xact; ListCell *cell; char *name = NULL; switch (s->blockState) { /* * We can't rollback to a savepoint if there is no savepoint * defined. */ case TBLOCK_INPROGRESS: case TBLOCK_ABORT: ereport(ERROR, (errcode(ERRCODE_S_E_INVALID_SPECIFICATION), errmsg("no such savepoint"))); break; /* * There is at least one savepoint, so proceed. */ case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBABORT: break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_STARTED: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "RollbackToSavepoint: unexpected state %s", BlockStateAsString(s->blockState)); break; } foreach(cell, options) { DefElem *elem = lfirst(cell); if (strcmp(elem->defname, "savepoint_name") == 0) name = strVal(elem->arg); } Assert(PointerIsValid(name)); for (target = s; PointerIsValid(target); target = target->parent) { if (PointerIsValid(target->name) && strcmp(target->name, name) == 0) break; } if (!PointerIsValid(target)) ereport(ERROR, (errcode(ERRCODE_S_E_INVALID_SPECIFICATION), errmsg("no such savepoint"))); /* disallow crossing savepoint level boundaries */ if (target->savepointLevel != s->savepointLevel) ereport(ERROR, (errcode(ERRCODE_S_E_INVALID_SPECIFICATION), errmsg("no such savepoint"))); /* * Mark "abort pending" all subtransactions up to the target * subtransaction. The actual aborts will happen when control gets to * CommitTransactionCommand. */ xact = CurrentTransactionState; for (;;) { if (xact == target) break; if (xact->blockState == TBLOCK_SUBINPROGRESS) xact->blockState = TBLOCK_SUBABORT_PENDING; else if (xact->blockState == TBLOCK_SUBABORT) xact->blockState = TBLOCK_SUBABORT_END; else elog(FATAL, "RollbackToSavepoint: unexpected state %s", BlockStateAsString(xact->blockState)); xact = xact->parent; Assert(PointerIsValid(xact)); } /* And mark the target as "restart pending" */ if (xact->blockState == TBLOCK_SUBINPROGRESS) xact->blockState = TBLOCK_SUBRESTART; else if (xact->blockState == TBLOCK_SUBABORT) xact->blockState = TBLOCK_SUBABORT_RESTART; else elog(FATAL, "RollbackToSavepoint: unexpected state %s", BlockStateAsString(xact->blockState)); }
void SetCurrentStatementStartTimestamp | ( | void | ) |
Definition at line 648 of file xact.c.
References GetCurrentTimestamp(), and stmtStartTimestamp.
Referenced by autovac_report_activity(), initialize_worker_spi(), InitPostgres(), PostgresMain(), and worker_spi_main().
{ stmtStartTimestamp = GetCurrentTimestamp(); }
static void SetCurrentTransactionStopTimestamp | ( | void | ) | [inline, static] |
Definition at line 657 of file xact.c.
References GetCurrentTimestamp(), and xactStopTimestamp.
Referenced by RecordTransactionAbort(), and RecordTransactionCommit().
{ xactStopTimestamp = GetCurrentTimestamp(); }
static void ShowTransactionState | ( | const char * | str | ) | [static] |
Definition at line 4412 of file xact.c.
References client_min_messages, DEBUG3, elog, log_min_messages, and ShowTransactionStateRec().
Referenced by AbortSubTransaction(), CleanupSubTransaction(), CommitSubTransaction(), CommitTransaction(), PrepareTransaction(), StartSubTransaction(), and StartTransaction().
{ /* skip work if message will definitely not be printed */ if (log_min_messages <= DEBUG3 || client_min_messages <= DEBUG3) { elog(DEBUG3, "%s", str); ShowTransactionStateRec(CurrentTransactionState); } }
static void ShowTransactionStateRec | ( | TransactionState | state | ) | [static] |
Definition at line 4427 of file xact.c.
References appendStringInfo(), TransactionStateData::blockState, BlockStateAsString(), buf, TransactionStateData::childXids, currentCommandId, currentCommandIdUsed, StringInfoData::data, DEBUG3, ereport, errmsg_internal(), i, initStringInfo(), TransactionStateData::name, TransactionStateData::nChildXids, TransactionStateData::nestingLevel, TransactionStateData::parent, pfree(), PointerIsValid, TransactionStateData::state, TransactionStateData::subTransactionId, TransactionStateData::transactionId, and TransStateAsString().
Referenced by ShowTransactionState().
{ StringInfoData buf; initStringInfo(&buf); if (s->nChildXids > 0) { int i; appendStringInfo(&buf, "%u", s->childXids[0]); for (i = 1; i < s->nChildXids; i++) appendStringInfo(&buf, " %u", s->childXids[i]); } if (s->parent) ShowTransactionStateRec(s->parent); /* use ereport to suppress computation if msg will not be printed */ ereport(DEBUG3, (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/subid/cid: %u/%u/%u%s, nestlvl: %d, children: %s", PointerIsValid(s->name) ? s->name : "unnamed", BlockStateAsString(s->blockState), TransStateAsString(s->state), (unsigned int) s->transactionId, (unsigned int) s->subTransactionId, (unsigned int) currentCommandId, currentCommandIdUsed ? " (used)" : "", s->nestingLevel, buf.data))); pfree(buf.data); }
static void StartSubTransaction | ( | void | ) | [static] |
Definition at line 4037 of file xact.c.
References AfterTriggerBeginSubXact(), AtSubStart_Inval(), AtSubStart_Memory(), AtSubStart_Notify(), AtSubStart_ResourceOwner(), CallSubXactCallbacks(), elog, TransactionStateData::parent, ShowTransactionState(), TransactionStateData::state, TransactionStateData::subTransactionId, SUBXACT_EVENT_START_SUB, TRANS_DEFAULT, TransStateAsString(), and WARNING.
Referenced by CommitTransactionCommand().
{ TransactionState s = CurrentTransactionState; if (s->state != TRANS_DEFAULT) elog(WARNING, "StartSubTransaction while in %s state", TransStateAsString(s->state)); s->state = TRANS_START; /* * Initialize subsystems for new subtransaction * * must initialize resource-management stuff first */ AtSubStart_Memory(); AtSubStart_ResourceOwner(); AtSubStart_Inval(); AtSubStart_Notify(); AfterTriggerBeginSubXact(); s->state = TRANS_INPROGRESS; /* * Call start-of-subxact callbacks */ CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId, s->parent->subTransactionId); ShowTransactionState("StartSubTransaction"); }
static void StartTransaction | ( | void | ) | [static] |
Definition at line 1676 of file xact.c.
References AfterTriggerBeginXact(), Assert, AtStart_Cache(), AtStart_GUC(), AtStart_Inval(), AtStart_Memory(), AtStart_ResourceOwner(), PGPROC::backendId, VirtualTransactionId::backendId, TransactionStateData::childXids, currentCommandId, currentCommandIdUsed, currentSubTransactionId, DefaultXactDeferrable, DefaultXactIsoLevel, DefaultXactReadOnly, elog, forceSyncCommit, GetNextLocalTransactionId(), GetUserIdAndSecContext(), TransactionStateData::gucNestLevel, VirtualTransactionId::localTransactionId, PGPROC::lxid, TransactionStateData::maxChildXids, MyBackendId, MyProc, MyXactAccessedTempRel, TransactionStateData::nChildXids, TransactionStateData::nestingLevel, nUnreportedXids, pgstat_report_xact_timestamp(), TransactionStateData::prevSecContext, TransactionStateData::prevUser, RecoveryInProgress(), ShowTransactionState(), TransactionStateData::startedInRecovery, TransactionStateData::state, stmtStartTimestamp, TransactionStateData::subTransactionId, TRANS_DEFAULT, TransactionStateData::transactionId, TransStateAsString(), VirtualXactLockTableInsert(), WARNING, XactDeferrable, XactIsoLevel, XactReadOnly, xactStartTimestamp, and xactStopTimestamp.
Referenced by restore_toc_entry(), RestoreArchive(), StartRestoreBlobs(), and StartTransactionCommand().
{ TransactionState s; VirtualTransactionId vxid; /* * Let's just make sure the state stack is empty */ s = &TopTransactionStateData; CurrentTransactionState = s; /* * check the current transaction state */ if (s->state != TRANS_DEFAULT) elog(WARNING, "StartTransaction while in %s state", TransStateAsString(s->state)); /* * set the current transaction state information appropriately during * start processing */ s->state = TRANS_START; s->transactionId = InvalidTransactionId; /* until assigned */ /* * Make sure we've reset xact state variables * * If recovery is still in progress, mark this transaction as read-only. * We have lower level defences in XLogInsert and elsewhere to stop us * from modifying data during recovery, but this gives the normal * indication to the user that the transaction is read-only. */ if (RecoveryInProgress()) { s->startedInRecovery = true; XactReadOnly = true; } else { s->startedInRecovery = false; XactReadOnly = DefaultXactReadOnly; } XactDeferrable = DefaultXactDeferrable; XactIsoLevel = DefaultXactIsoLevel; forceSyncCommit = false; MyXactAccessedTempRel = false; /* * reinitialize within-transaction counters */ s->subTransactionId = TopSubTransactionId; currentSubTransactionId = TopSubTransactionId; currentCommandId = FirstCommandId; currentCommandIdUsed = false; /* * initialize reported xid accounting */ nUnreportedXids = 0; /* * must initialize resource-management stuff first */ AtStart_Memory(); AtStart_ResourceOwner(); /* * Assign a new LocalTransactionId, and combine it with the backendId to * form a virtual transaction id. */ vxid.backendId = MyBackendId; vxid.localTransactionId = GetNextLocalTransactionId(); /* * Lock the virtual transaction id before we announce it in the proc array */ VirtualXactLockTableInsert(vxid); /* * Advertise it in the proc array. We assume assignment of * LocalTransactionID is atomic, and the backendId should be set already. */ Assert(MyProc->backendId == vxid.backendId); MyProc->lxid = vxid.localTransactionId; TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId); /* * set transaction_timestamp() (a/k/a now()). We want this to be the same * as the first command's statement_timestamp(), so don't do a fresh * GetCurrentTimestamp() call (which'd be expensive anyway). Also, mark * xactStopTimestamp as unset. */ xactStartTimestamp = stmtStartTimestamp; xactStopTimestamp = 0; pgstat_report_xact_timestamp(xactStartTimestamp); /* * initialize current transaction state fields * * note: prevXactReadOnly is not used at the outermost level */ s->nestingLevel = 1; s->gucNestLevel = 1; s->childXids = NULL; s->nChildXids = 0; s->maxChildXids = 0; GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext); /* SecurityRestrictionContext should never be set outside a transaction */ Assert(s->prevSecContext == 0); /* * initialize other subsystems for new transaction */ AtStart_GUC(); AtStart_Inval(); AtStart_Cache(); AfterTriggerBeginXact(); /* * done with start processing, set current transaction state to "in * progress" */ s->state = TRANS_INPROGRESS; ShowTransactionState("StartTransaction"); }
void StartTransactionCommand | ( | void | ) |
Definition at line 2439 of file xact.c.
References Assert, TransactionStateData::blockState, BlockStateAsString(), CurTransactionContext, elog, ERROR, MemoryContextSwitchTo(), NULL, StartTransaction(), TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by BeginInternalSubTransaction(), cluster(), DefineIndex(), do_autovacuum(), get_database_list(), index_drop(), initialize_worker_spi(), InitPostgres(), movedb(), ProcessCatchupEvent(), ProcessCompletedNotifies(), ProcessIncomingNotify(), ReindexDatabase(), RemoveTempRelationsCallback(), start_xact_command(), vacuum(), vacuum_rel(), and worker_spi_main().
{ 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(); s->blockState = TBLOCK_STARTED; break; /* * We are somewhere in a transaction block or subtransaction and * about to start a new command. For now we do nothing, but * someday we may do command-local resource initialization. (Note * that any needed CommandCounterIncrement was done by the * previous CommitTransactionCommand.) */ case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: break; /* * Here we are in a failed transaction block (one of the commands * caused an abort) so we do nothing but remain in the abort * state. Eventually we will get a ROLLBACK command which will * get us out of this state. (It is up to other code to ensure * that no commands other than ROLLBACK will be processed in these * states.) */ case TBLOCK_ABORT: case TBLOCK_SUBABORT: break; /* These cases are invalid. */ case TBLOCK_STARTED: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(ERROR, "StartTransactionCommand: unexpected state %s", BlockStateAsString(s->blockState)); break; } /* * We must switch to CurTransactionContext before returning. This is * already done if we called StartTransaction, otherwise not. */ Assert(CurTransactionContext != NULL); MemoryContextSwitchTo(CurTransactionContext); }
bool SubTransactionIsActive | ( | SubTransactionId | subxid | ) |
Definition at line 580 of file xact.c.
References TransactionStateData::parent, TransactionStateData::state, TransactionStateData::subTransactionId, and TRANS_ABORT.
Referenced by fmgr_sql().
{ TransactionState s; for (s = CurrentTransactionState; s != NULL; s = s->parent) { if (s->state == TRANS_ABORT) continue; if (s->subTransactionId == subxid) return true; } return false; }
char TransactionBlockStatusCode | ( | void | ) |
Definition at line 3975 of file xact.c.
References TransactionStateData::blockState, BlockStateAsString(), elog, FATAL, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by ReadyForQuery().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { case TBLOCK_DEFAULT: case TBLOCK_STARTED: return 'I'; /* idle --- not in transaction */ case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_PREPARE: return 'T'; /* in transaction */ case TBLOCK_ABORT: case TBLOCK_SUBABORT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: return 'E'; /* in failed transaction */ } /* should never get here */ elog(FATAL, "invalid transaction block state: %s", BlockStateAsString(s->blockState)); return 0; /* keep compiler quiet */ }
bool TransactionIdIsCurrentTransactionId | ( | TransactionId | xid | ) |
Definition at line 681 of file xact.c.
References TransactionStateData::childXids, TransactionStateData::nChildXids, TransactionStateData::parent, TransactionStateData::state, TRANS_ABORT, TransactionStateData::transactionId, TransactionIdEquals, TransactionIdIsNormal, TransactionIdIsValid, and TransactionIdPrecedes().
Referenced by acquire_sample_rows(), copy_heap_data(), Do_MultiXactIdWait(), EvalPlanQualFetch(), funny_dup17(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), HeapTupleHeaderAdjustCmax(), HeapTupleHeaderGetCmax(), HeapTupleHeaderGetCmin(), HeapTupleHeaderIsOnlyLocked(), HeapTupleSatisfiesDirty(), HeapTupleSatisfiesMVCC(), HeapTupleSatisfiesNow(), HeapTupleSatisfiesSelf(), HeapTupleSatisfiesToast(), HeapTupleSatisfiesUpdate(), HeapTupleSatisfiesVacuum(), IndexBuildHeapScan(), MultiXactIdIsRunning(), RI_FKey_fk_upd_check_required(), and TransactionIdIsInProgress().
{ TransactionState s; /* * We always say that BootstrapTransactionId is "not my transaction ID" * even when it is (ie, during bootstrap). Along with the fact that * transam.c always treats BootstrapTransactionId as already committed, * this causes the tqual.c routines to see all tuples as committed, which * is what we need during bootstrap. (Bootstrap mode only inserts tuples, * it never updates or deletes them, so all tuples can be presumed good * immediately.) * * Likewise, InvalidTransactionId and FrozenTransactionId are certainly * not my transaction ID, so we can just return "false" immediately for * any non-normal XID. */ if (!TransactionIdIsNormal(xid)) return false; /* * We will return true for the Xid of the current subtransaction, any of * its subcommitted children, any of its parents, or any of their * previously subcommitted children. However, a transaction being aborted * is no longer "current", even though it may still have an entry on the * state stack. */ for (s = CurrentTransactionState; s != NULL; s = s->parent) { int low, high; if (s->state == TRANS_ABORT) continue; if (!TransactionIdIsValid(s->transactionId)) continue; /* it can't have any child XIDs either */ if (TransactionIdEquals(xid, s->transactionId)) return true; /* As the childXids array is ordered, we can use binary search */ low = 0; high = s->nChildXids - 1; while (low <= high) { int middle; TransactionId probe; middle = low + (high - low) / 2; probe = s->childXids[middle]; if (TransactionIdEquals(probe, xid)) return true; else if (TransactionIdPrecedes(probe, xid)) low = middle + 1; else high = middle - 1; } } return false; }
bool TransactionStartedDuringRecovery | ( | void | ) |
Definition at line 749 of file xact.c.
References TransactionStateData::startedInRecovery.
Referenced by RelationGetIndexScan().
{ return CurrentTransactionState->startedInRecovery; }
static const char * TransStateAsString | ( | TransState | state | ) | [static] |
Definition at line 4514 of file xact.c.
References TRANS_ABORT, TRANS_COMMIT, TRANS_DEFAULT, TRANS_INPROGRESS, TRANS_PREPARE, and TRANS_START.
Referenced by AbortSubTransaction(), AbortTransaction(), CleanupSubTransaction(), CleanupTransaction(), CommitSubTransaction(), CommitTransaction(), PopTransaction(), PrepareTransaction(), ShowTransactionStateRec(), StartSubTransaction(), and StartTransaction().
{ switch (state) { case TRANS_DEFAULT: return "DEFAULT"; case TRANS_START: return "START"; case TRANS_INPROGRESS: return "INPROGR"; case TRANS_COMMIT: return "COMMIT"; case TRANS_ABORT: return "ABORT"; case TRANS_PREPARE: return "PREPARE"; } return "UNRECOGNIZED"; }
void UnregisterSubXactCallback | ( | SubXactCallback | callback, | |
void * | arg | |||
) |
Definition at line 3110 of file xact.c.
References SubXactCallbackItem::next, and pfree().
{ SubXactCallbackItem *item; SubXactCallbackItem *prev; prev = NULL; for (item = SubXact_callbacks; item; prev = item, item = item->next) { if (item->callback == callback && item->arg == arg) { if (prev) prev->next = item->next; else SubXact_callbacks = item->next; pfree(item); break; } } }
void UnregisterXactCallback | ( | XactCallback | callback, | |
void * | arg | |||
) |
Definition at line 3055 of file xact.c.
References XactCallbackItem::next, and pfree().
{ XactCallbackItem *item; XactCallbackItem *prev; prev = NULL; for (item = Xact_callbacks; item; prev = item, item = item->next) { if (item->callback == callback && item->arg == arg) { if (prev) prev->next = item->next; else Xact_callbacks = item->next; pfree(item); break; } } }
void UserAbortTransactionBlock | ( | void | ) |
Definition at line 3375 of file xact.c.
References TransactionStateData::blockState, BlockStateAsString(), elog, ereport, errcode(), errmsg(), FATAL, NOTICE, NULL, TransactionStateData::parent, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING, TBLOCK_BEGIN, TBLOCK_DEFAULT, TBLOCK_END, TBLOCK_INPROGRESS, TBLOCK_PREPARE, TBLOCK_STARTED, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING, TBLOCK_SUBABORT_RESTART, TBLOCK_SUBBEGIN, TBLOCK_SUBCOMMIT, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE, and TBLOCK_SUBRESTART.
Referenced by standard_ProcessUtility().
{ TransactionState s = CurrentTransactionState; switch (s->blockState) { /* * We are inside a transaction block and we got a ROLLBACK command * from the user, so tell CommitTransactionCommand to abort and * exit the transaction block. */ case TBLOCK_INPROGRESS: s->blockState = TBLOCK_ABORT_PENDING; break; /* * We are inside a failed transaction block and we got a ROLLBACK * command from the user. Abort processing is already done, so * CommitTransactionCommand just has to cleanup and go back to * idle state. */ case TBLOCK_ABORT: s->blockState = TBLOCK_ABORT_END; break; /* * We are inside a subtransaction. Mark everything up to top * level as exitable. */ case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBABORT: while (s->parent != NULL) { if (s->blockState == TBLOCK_SUBINPROGRESS) s->blockState = TBLOCK_SUBABORT_PENDING; else if (s->blockState == TBLOCK_SUBABORT) s->blockState = TBLOCK_SUBABORT_END; else elog(FATAL, "UserAbortTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); s = s->parent; } if (s->blockState == TBLOCK_INPROGRESS) s->blockState = TBLOCK_ABORT_PENDING; else if (s->blockState == TBLOCK_ABORT) s->blockState = TBLOCK_ABORT_END; else elog(FATAL, "UserAbortTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; /* * The user issued ABORT when not inside a transaction. Issue a * NOTICE and go to abort state. The upcoming call to * CommitTransactionCommand() will then put us back into the * default state. */ case TBLOCK_STARTED: ereport(NOTICE, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), errmsg("there is no transaction in progress"))); s->blockState = TBLOCK_ABORT_PENDING; break; /* These cases are invalid. */ case TBLOCK_DEFAULT: case TBLOCK_BEGIN: case TBLOCK_SUBBEGIN: case TBLOCK_END: case TBLOCK_SUBRELEASE: case TBLOCK_SUBCOMMIT: case TBLOCK_ABORT_END: case TBLOCK_SUBABORT_END: case TBLOCK_ABORT_PENDING: case TBLOCK_SUBABORT_PENDING: case TBLOCK_SUBRESTART: case TBLOCK_SUBABORT_RESTART: case TBLOCK_PREPARE: elog(FATAL, "UserAbortTransactionBlock: unexpected state %s", BlockStateAsString(s->blockState)); break; } }
void xact_redo | ( | XLogRecPtr | lsn, | |
XLogRecord * | record | |||
) |
Definition at line 4822 of file xact.c.
References xl_xact_abort_prepared::arec, Assert, xl_xact_commit_prepared::crec, elog, xl_xact_assignment::nsubxacts, PANIC, ProcArrayApplyXidAssignment(), RecreateTwoPhaseFile(), RemoveTwoPhaseFile(), STANDBY_INITIALIZED, standbyState, xact_redo_abort(), xact_redo_commit(), xact_redo_commit_compact(), xl_xact_abort_prepared::xid, xl_xact_commit_prepared::xid, XLogRecord::xl_info, XLogRecord::xl_len, XLogRecord::xl_xid, XLOG_XACT_ABORT, XLOG_XACT_ABORT_PREPARED, XLOG_XACT_ASSIGNMENT, XLOG_XACT_COMMIT, XLOG_XACT_COMMIT_COMPACT, XLOG_XACT_COMMIT_PREPARED, XLOG_XACT_PREPARE, XLogRecGetData, XLR_BKP_BLOCK_MASK, xl_xact_assignment::xsub, and xl_xact_assignment::xtop.
{ uint8 info = record->xl_info & ~XLR_INFO_MASK; /* Backup blocks are not used in xact records */ Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK)); if (info == XLOG_XACT_COMMIT_COMPACT) { xl_xact_commit_compact *xlrec = (xl_xact_commit_compact *) XLogRecGetData(record); xact_redo_commit_compact(xlrec, record->xl_xid, lsn); } else if (info == XLOG_XACT_COMMIT) { xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record); xact_redo_commit(xlrec, record->xl_xid, lsn); } else if (info == XLOG_XACT_ABORT) { xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record); xact_redo_abort(xlrec, record->xl_xid); } else if (info == XLOG_XACT_PREPARE) { /* the record contents are exactly the 2PC file */ RecreateTwoPhaseFile(record->xl_xid, XLogRecGetData(record), record->xl_len); } else if (info == XLOG_XACT_COMMIT_PREPARED) { xl_xact_commit_prepared *xlrec = (xl_xact_commit_prepared *) XLogRecGetData(record); xact_redo_commit(&xlrec->crec, xlrec->xid, lsn); RemoveTwoPhaseFile(xlrec->xid, false); } else if (info == XLOG_XACT_ABORT_PREPARED) { xl_xact_abort_prepared *xlrec = (xl_xact_abort_prepared *) XLogRecGetData(record); xact_redo_abort(&xlrec->arec, xlrec->xid); RemoveTwoPhaseFile(xlrec->xid, false); } else if (info == XLOG_XACT_ASSIGNMENT) { xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record); if (standbyState >= STANDBY_INITIALIZED) ProcArrayApplyXidAssignment(xlrec->xtop, xlrec->nsubxacts, xlrec->xsub); } else elog(PANIC, "xact_redo: unknown op code %u", info); }
static void xact_redo_abort | ( | xl_xact_abort * | xlrec, | |
TransactionId | xid | |||
) | [static] |
Definition at line 4746 of file xact.c.
References ExpireTreeKnownAssignedTransactionIds(), i, InvalidBackendId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, xl_xact_abort::nrels, xl_xact_abort::nsubxacts, RecordKnownAssignedTransactionIds(), ShmemVariableCache, smgrclose(), smgrdounlink(), smgropen(), STANDBY_DISABLED, StandbyReleaseLockTree(), standbyState, TransactionIdAbortTree(), TransactionIdAdvance, TransactionIdFollowsOrEquals(), TransactionIdLatest(), XidGenLock, XLogDropRelation(), and xl_xact_abort::xnodes.
Referenced by xact_redo().
{ TransactionId *sub_xids; TransactionId max_xid; int i; sub_xids = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]); max_xid = TransactionIdLatest(xid, xlrec->nsubxacts, sub_xids); /* * Make sure nextXid is beyond any XID mentioned in the record. * * We don't expect anyone else to modify nextXid, hence we don't need to * hold a lock while checking this. We still acquire the lock to modify * it, though. */ if (TransactionIdFollowsOrEquals(max_xid, ShmemVariableCache->nextXid)) { LWLockAcquire(XidGenLock, LW_EXCLUSIVE); ShmemVariableCache->nextXid = max_xid; TransactionIdAdvance(ShmemVariableCache->nextXid); LWLockRelease(XidGenLock); } if (standbyState == STANDBY_DISABLED) { /* Mark the transaction aborted in pg_clog, no need for async stuff */ TransactionIdAbortTree(xid, xlrec->nsubxacts, sub_xids); } else { /* * If a transaction completion record arrives that has as-yet * unobserved subtransactions then this will not have been fully * handled by the call to RecordKnownAssignedTransactionIds() in the * main recovery loop in xlog.c. So we need to do bookkeeping again to * cover that case. This is confusing and it is easy to think this * call is irrelevant, which has happened three times in development * already. Leave it in. */ RecordKnownAssignedTransactionIds(max_xid); /* Mark the transaction aborted in pg_clog, no need for async stuff */ TransactionIdAbortTree(xid, xlrec->nsubxacts, sub_xids); /* * We must update the ProcArray after we have marked clog. */ ExpireTreeKnownAssignedTransactionIds(xid, xlrec->nsubxacts, sub_xids, max_xid); /* * There are no flat files that need updating, nor invalidation * messages to send or undo. */ /* * Release locks, if any. There are no invalidations to send. */ StandbyReleaseLockTree(xid, xlrec->nsubxacts, sub_xids); } /* Make sure files supposed to be dropped are dropped */ for (i = 0; i < xlrec->nrels; i++) { SMgrRelation srel = smgropen(xlrec->xnodes[i], InvalidBackendId); ForkNumber fork; for (fork = 0; fork <= MAX_FORKNUM; fork++) XLogDropRelation(xlrec->xnodes[i], fork); smgrdounlink(srel, true); smgrclose(srel); } }
static void xact_redo_commit | ( | xl_xact_commit * | xlrec, | |
TransactionId | xid, | |||
XLogRecPtr | lsn | |||
) | [static] |
Definition at line 4702 of file xact.c.
References xl_xact_commit::dbId, xl_xact_commit::nmsgs, xl_xact_commit::nrels, xl_xact_commit::nsubxacts, xl_xact_commit::tsId, xact_redo_commit_internal(), xl_xact_commit::xinfo, and xl_xact_commit::xnodes.
Referenced by xact_redo().
{ TransactionId *subxacts; SharedInvalidationMessage *inval_msgs; /* subxid array follows relfilenodes */ subxacts = (TransactionId *) &(xlrec->xnodes[xlrec->nrels]); /* invalidation messages array follows subxids */ inval_msgs = (SharedInvalidationMessage *) &(subxacts[xlrec->nsubxacts]); xact_redo_commit_internal(xid, lsn, subxacts, xlrec->nsubxacts, inval_msgs, xlrec->nmsgs, xlrec->xnodes, xlrec->nrels, xlrec->dbId, xlrec->tsId, xlrec->xinfo); }
static void xact_redo_commit_compact | ( | xl_xact_commit_compact * | xlrec, | |
TransactionId | xid, | |||
XLogRecPtr | lsn | |||
) | [static] |
Definition at line 4725 of file xact.c.
References InvalidOid, xl_xact_commit_compact::nsubxacts, NULL, xl_xact_commit_compact::subxacts, and xact_redo_commit_internal().
Referenced by xact_redo().
{ xact_redo_commit_internal(xid, lsn, xlrec->subxacts, xlrec->nsubxacts, NULL, 0, /* inval msgs */ NULL, 0, /* relfilenodes */ InvalidOid, /* dbId */ InvalidOid, /* tsId */ 0); /* xinfo */ }
static void xact_redo_commit_internal | ( | TransactionId | xid, | |
XLogRecPtr | lsn, | |||
TransactionId * | sub_xids, | |||
int | nsubxacts, | |||
SharedInvalidationMessage * | inval_msgs, | |||
int | nmsgs, | |||
RelFileNode * | xnodes, | |||
int | nrels, | |||
Oid | dbId, | |||
Oid | tsId, | |||
uint32 | xinfo | |||
) | [static] |
Definition at line 4565 of file xact.c.
References ExpireTreeKnownAssignedTransactionIds(), i, InvalidBackendId, LW_EXCLUSIVE, LWLockAcquire(), LWLockRelease(), VariableCacheData::nextXid, NULL, ProcessCommittedInvalidationMessages(), RecordKnownAssignedTransactionIds(), ShmemVariableCache, smgrclose(), smgrdounlink(), smgropen(), STANDBY_DISABLED, StandbyReleaseLockTree(), standbyState, TransactionIdAdvance, TransactionIdAsyncCommitTree(), TransactionIdCommitTree(), TransactionIdFollowsOrEquals(), TransactionIdLatest(), XactCompletionForceSyncCommit, XactCompletionRelcacheInitFileInval, XidGenLock, XLogDropRelation(), and XLogFlush().
Referenced by xact_redo_commit(), and xact_redo_commit_compact().
{ TransactionId max_xid; int i; max_xid = TransactionIdLatest(xid, nsubxacts, sub_xids); /* * Make sure nextXid is beyond any XID mentioned in the record. * * We don't expect anyone else to modify nextXid, hence we don't need to * hold a lock while checking this. We still acquire the lock to modify * it, though. */ if (TransactionIdFollowsOrEquals(max_xid, ShmemVariableCache->nextXid)) { LWLockAcquire(XidGenLock, LW_EXCLUSIVE); ShmemVariableCache->nextXid = max_xid; TransactionIdAdvance(ShmemVariableCache->nextXid); LWLockRelease(XidGenLock); } if (standbyState == STANDBY_DISABLED) { /* * Mark the transaction committed in pg_clog. */ TransactionIdCommitTree(xid, nsubxacts, sub_xids); } else { /* * If a transaction completion record arrives that has as-yet * unobserved subtransactions then this will not have been fully * handled by the call to RecordKnownAssignedTransactionIds() in the * main recovery loop in xlog.c. So we need to do bookkeeping again to * cover that case. This is confusing and it is easy to think this * call is irrelevant, which has happened three times in development * already. Leave it in. */ RecordKnownAssignedTransactionIds(max_xid); /* * Mark the transaction committed in pg_clog. We use async commit * protocol during recovery to provide information on database * consistency for when users try to set hint bits. It is important * that we do not set hint bits until the minRecoveryPoint is past * this commit record. This ensures that if we crash we don't see hint * bits set on changes made by transactions that haven't yet * recovered. It's unlikely but it's good to be safe. */ TransactionIdAsyncCommitTree(xid, nsubxacts, sub_xids, lsn); /* * We must mark clog before we update the ProcArray. */ ExpireTreeKnownAssignedTransactionIds(xid, nsubxacts, sub_xids, max_xid); /* * Send any cache invalidations attached to the commit. We must * maintain the same order of invalidation then release locks as * occurs in CommitTransaction(). */ ProcessCommittedInvalidationMessages(inval_msgs, nmsgs, XactCompletionRelcacheInitFileInval(xinfo), dbId, tsId); /* * Release locks, if any. We do this for both two phase and normal one * phase transactions. In effect we are ignoring the prepare phase and * just going straight to lock release. At commit we release all locks * via their top-level xid only, so no need to provide subxact list, * which will save time when replaying commits. */ StandbyReleaseLockTree(xid, 0, NULL); } /* Make sure files supposed to be dropped are dropped */ if (nrels > 0) { /* * First update minimum recovery point to cover this WAL record. Once * a relation is deleted, there's no going back. The buffer manager * enforces the WAL-first rule for normal updates to relation files, * so that the minimum recovery point is always updated before the * corresponding change in the data file is flushed to disk, but we * have to do the same here since we're bypassing the buffer manager. * * Doing this before deleting the files means that if a deletion fails * for some reason, you cannot start up the system even after restart, * until you fix the underlying situation so that the deletion will * succeed. Alternatively, we could update the minimum recovery point * after deletion, but that would leave a small window where the * WAL-first rule would be violated. */ XLogFlush(lsn); for (i = 0; i < nrels; i++) { SMgrRelation srel = smgropen(xnodes[i], InvalidBackendId); ForkNumber fork; for (fork = 0; fork <= MAX_FORKNUM; fork++) XLogDropRelation(xnodes[i], fork); smgrdounlink(srel, true); smgrclose(srel); } } /* * We issue an XLogFlush() for the same reason we emit ForceSyncCommit() * in normal operation. For example, in CREATE DATABASE, we copy all files * from the template database, and then commit the transaction. If we * crash after all the files have been copied but before the commit, you * have files in the data directory without an entry in pg_database. To * minimize the window * for that, we use ForceSyncCommit() to rush the commit record to disk as * quick as possible. We have the same window during recovery, and forcing * an XLogFlush() (which updates minRecoveryPoint during recovery) helps * to reduce that problem window, for any user that requested * ForceSyncCommit(). */ if (XactCompletionForceSyncCommit(xinfo)) XLogFlush(lsn); }
int xactGetCommittedChildren | ( | TransactionId ** | ptr | ) |
Definition at line 4544 of file xact.c.
References TransactionStateData::childXids, and TransactionStateData::nChildXids.
Referenced by ExportSnapshot(), RecordTransactionAbort(), RecordTransactionCommit(), and StartPrepare().
{ TransactionState s = CurrentTransactionState; if (s->nChildXids == 0) *ptr = NULL; else *ptr = s->childXids; return s->nChildXids; }
CommandId currentCommandId [static] |
Definition at line 195 of file xact.c.
Referenced by CommandCounterIncrement(), GetCurrentCommandId(), ShowTransactionStateRec(), and StartTransaction().
bool currentCommandIdUsed [static] |
Definition at line 196 of file xact.c.
Referenced by CommandCounterIncrement(), GetCurrentCommandId(), ShowTransactionStateRec(), and StartTransaction().
SubTransactionId currentSubTransactionId [static] |
Definition at line 194 of file xact.c.
Referenced by PushTransaction(), and StartTransaction().
bool DefaultXactDeferrable = false |
Definition at line 68 of file xact.c.
Referenced by StartTransaction().
int DefaultXactIsoLevel = XACT_READ_COMMITTED |
Definition at line 62 of file xact.c.
Referenced by check_XactIsoLevel(), and StartTransaction().
bool DefaultXactReadOnly = false |
Definition at line 65 of file xact.c.
Referenced by StartTransaction().
bool forceSyncCommit = false [static] |
Definition at line 218 of file xact.c.
Referenced by ForceSyncCommit(), RecordTransactionCommit(), and StartTransaction().
bool MyXactAccessedTempRel = false |
Definition at line 78 of file xact.c.
Referenced by PreCommit_on_commit_actions(), PrepareTransaction(), relation_open(), StartTransaction(), and try_relation_open().
int nUnreportedXids [static] |
Definition at line 185 of file xact.c.
Referenced by AssignTransactionId(), and StartTransaction().
char* prepareGID [static] |
Definition at line 213 of file xact.c.
Referenced by PrepareTransaction(), and PrepareTransactionBlock().
TimestampTz stmtStartTimestamp [static] |
Definition at line 206 of file xact.c.
Referenced by GetCurrentStatementStartTimestamp(), SetCurrentStatementStartTimestamp(), and StartTransaction().
SubXactCallbackItem* SubXact_callbacks = NULL [static] |
int synchronous_commit = SYNCHRONOUS_COMMIT_ON |
Definition at line 71 of file xact.c.
Referenced by AutoVacWorkerMain(), and RecordTransactionCommit().
MemoryContext TransactionAbortContext = NULL [static] |
TransactionId unreportedXids[PGPROC_MAX_CACHED_SUBXIDS] [static] |
Definition at line 186 of file xact.c.
Referenced by AssignTransactionId().
XactCallbackItem* Xact_callbacks = NULL [static] |
Definition at line 69 of file xact.c.
Referenced by GetSafeSnapshot(), GetSerializableTransactionSnapshot(), SetSerializableTransactionSnapshot(), and StartTransaction().
int XactIsoLevel |
Definition at line 63 of file xact.c.
Referenced by assign_XactIsoLevel(), check_XactIsoLevel(), ExportSnapshot(), InitPostgres(), show_XactIsoLevel(), and StartTransaction().
Definition at line 66 of file xact.c.
Referenced by AbortSubTransaction(), check_transaction_read_only(), check_xact_readonly(), CommitSubTransaction(), DoCopy(), ExportSnapshot(), GetSafeSnapshot(), GetSerializableTransactionSnapshot(), GetSerializableTransactionSnapshotInt(), ImportSnapshot(), PreventCommandIfReadOnly(), PushTransaction(), SetSerializableTransactionSnapshot(), standard_ExecutorStart(), and StartTransaction().
TimestampTz xactStartTimestamp [static] |
Definition at line 205 of file xact.c.
Referenced by GetCurrentTransactionStartTimestamp(), and StartTransaction().
TimestampTz xactStopTimestamp [static] |
Definition at line 207 of file xact.c.
Referenced by GetCurrentTransactionStopTimestamp(), RecordTransactionAbort(), RecordTransactionCommit(), SetCurrentTransactionStopTimestamp(), and StartTransaction().