Header And Logo

PostgreSQL
| The world's most advanced open source database.

Data Structures | Typedefs | Enumerations | Functions | Variables

xact.c File Reference

#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"
Include dependency graph for xact.c:

Go to the source code of this file.

Data Structures

struct  TransactionStateData
struct  XactCallbackItem
struct  SubXactCallbackItem

Typedefs

typedef enum TransState TransState
typedef enum TBlockState TBlockState
typedef struct TransactionStateData TransactionStateData
typedef TransactionStateDataTransactionState
typedef struct XactCallbackItem XactCallbackItem
typedef struct SubXactCallbackItem SubXactCallbackItem

Enumerations

enum  TransState {
  TRANS_DEFAULT, TRANS_START, TRANS_INPROGRESS, TRANS_COMMIT,
  TRANS_ABORT, TRANS_PREPARE
}
enum  TBlockState {
  TBLOCK_DEFAULT, TBLOCK_STARTED, TBLOCK_BEGIN, TBLOCK_INPROGRESS,
  TBLOCK_END, TBLOCK_ABORT, TBLOCK_ABORT_END, TBLOCK_ABORT_PENDING,
  TBLOCK_PREPARE, TBLOCK_SUBBEGIN, TBLOCK_SUBINPROGRESS, TBLOCK_SUBRELEASE,
  TBLOCK_SUBCOMMIT, TBLOCK_SUBABORT, TBLOCK_SUBABORT_END, TBLOCK_SUBABORT_PENDING,
  TBLOCK_SUBRESTART, TBLOCK_SUBABORT_RESTART
}

Functions

static void AssignTransactionId (TransactionState s)
static void AbortTransaction (void)
static void AtAbort_Memory (void)
static void AtCleanup_Memory (void)
static void AtAbort_ResourceOwner (void)
static void AtCCI_LocalCache (void)
static void AtCommit_Memory (void)
static void AtStart_Cache (void)
static void AtStart_Memory (void)
static void AtStart_ResourceOwner (void)
static void CallXactCallbacks (XactEvent event)
static void CallSubXactCallbacks (SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid)
static void CleanupTransaction (void)
static void CommitTransaction (void)
static TransactionId RecordTransactionAbort (bool isSubXact)
static void StartTransaction (void)
static void StartSubTransaction (void)
static void CommitSubTransaction (void)
static void AbortSubTransaction (void)
static void CleanupSubTransaction (void)
static void PushTransaction (void)
static void PopTransaction (void)
static void AtSubAbort_Memory (void)
static void AtSubCleanup_Memory (void)
static void AtSubAbort_ResourceOwner (void)
static void AtSubCommit_Memory (void)
static void AtSubStart_Memory (void)
static void AtSubStart_ResourceOwner (void)
static void ShowTransactionState (const char *str)
static void ShowTransactionStateRec (TransactionState state)
static const char * BlockStateAsString (TBlockState blockState)
static const char * TransStateAsString (TransState state)
bool IsTransactionState (void)
bool IsAbortedTransactionBlockState (void)
TransactionId GetTopTransactionId (void)
TransactionId GetTopTransactionIdIfAny (void)
TransactionId GetCurrentTransactionId (void)
TransactionId GetCurrentTransactionIdIfAny (void)
TransactionId GetStableLatestTransactionId (void)
SubTransactionId GetCurrentSubTransactionId (void)
bool SubTransactionIsActive (SubTransactionId subxid)
CommandId GetCurrentCommandId (bool used)
TimestampTz GetCurrentTransactionStartTimestamp (void)
TimestampTz GetCurrentStatementStartTimestamp (void)
TimestampTz GetCurrentTransactionStopTimestamp (void)
void SetCurrentStatementStartTimestamp (void)
static void SetCurrentTransactionStopTimestamp (void)
int GetCurrentTransactionNestLevel (void)
bool TransactionIdIsCurrentTransactionId (TransactionId xid)
bool TransactionStartedDuringRecovery (void)
void CommandCounterIncrement (void)
void ForceSyncCommit (void)
static TransactionId RecordTransactionCommit (void)
static void AtSubCommit_childXids (void)
static void AtSubAbort_childXids (void)
static void PrepareTransaction (void)
void StartTransactionCommand (void)
void CommitTransactionCommand (void)
void AbortCurrentTransaction (void)
void PreventTransactionChain (bool isTopLevel, const char *stmtType)
void RequireTransactionChain (bool isTopLevel, const char *stmtType)
bool IsInTransactionChain (bool isTopLevel)
void RegisterXactCallback (XactCallback callback, void *arg)
void UnregisterXactCallback (XactCallback callback, void *arg)
void RegisterSubXactCallback (SubXactCallback callback, void *arg)
void UnregisterSubXactCallback (SubXactCallback callback, void *arg)
void BeginTransactionBlock (void)
bool PrepareTransactionBlock (char *gid)
bool EndTransactionBlock (void)
void UserAbortTransactionBlock (void)
void DefineSavepoint (char *name)
void ReleaseSavepoint (List *options)
void RollbackToSavepoint (List *options)
void BeginInternalSubTransaction (char *name)
void ReleaseCurrentSubTransaction (void)
void RollbackAndReleaseCurrentSubTransaction (void)
void AbortOutOfAnyTransaction (void)
bool IsTransactionBlock (void)
bool IsTransactionOrTransactionBlock (void)
char TransactionBlockStatusCode (void)
bool IsSubTransaction (void)
int xactGetCommittedChildren (TransactionId **ptr)
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 void xact_redo_commit (xl_xact_commit *xlrec, TransactionId xid, XLogRecPtr lsn)
static void xact_redo_commit_compact (xl_xact_commit_compact *xlrec, TransactionId xid, XLogRecPtr lsn)
static void xact_redo_abort (xl_xact_abort *xlrec, TransactionId xid)
void xact_redo (XLogRecPtr lsn, XLogRecord *record)

Variables

int DefaultXactIsoLevel = XACT_READ_COMMITTED
int XactIsoLevel
bool DefaultXactReadOnly = false
bool XactReadOnly
bool DefaultXactDeferrable = false
bool XactDeferrable
int synchronous_commit = SYNCHRONOUS_COMMIT_ON
bool MyXactAccessedTempRel = false
static TransactionStateData TopTransactionStateData
static int nUnreportedXids
static TransactionId unreportedXids [PGPROC_MAX_CACHED_SUBXIDS]
static TransactionState CurrentTransactionState = &TopTransactionStateData
static SubTransactionId currentSubTransactionId
static CommandId currentCommandId
static bool currentCommandIdUsed
static TimestampTz xactStartTimestamp
static TimestampTz stmtStartTimestamp
static TimestampTz xactStopTimestamp
static char * prepareGID
static bool forceSyncCommit = false
static MemoryContext TransactionAbortContext = NULL
static XactCallbackItemXact_callbacks = NULL
static SubXactCallbackItemSubXact_callbacks = NULL

Typedef Documentation

typedef enum TBlockState TBlockState

Definition at line 152 of file xact.c.

typedef enum TransState TransState

Enumeration Type Documentation

Enumerator:
TBLOCK_DEFAULT 
TBLOCK_STARTED 
TBLOCK_BEGIN 
TBLOCK_INPROGRESS 
TBLOCK_END 
TBLOCK_ABORT 
TBLOCK_ABORT_END 
TBLOCK_ABORT_PENDING 
TBLOCK_PREPARE 
TBLOCK_SUBBEGIN 
TBLOCK_SUBINPROGRESS 
TBLOCK_SUBRELEASE 
TBLOCK_SUBCOMMIT 
TBLOCK_SUBABORT 
TBLOCK_SUBABORT_END 
TBLOCK_SUBABORT_PENDING 
TBLOCK_SUBRESTART 
TBLOCK_SUBABORT_RESTART 

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
Enumerator:
TRANS_DEFAULT 
TRANS_START 
TRANS_INPROGRESS 
TRANS_COMMIT 
TRANS_ABORT 
TRANS_PREPARE 

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;


Function Documentation

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().

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]
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]
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]
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;
}

CommandId GetCurrentCommandId ( bool  used  ) 
TimestampTz GetCurrentStatementStartTimestamp ( void   ) 
SubTransactionId GetCurrentSubTransactionId ( void   ) 
TransactionId GetCurrentTransactionId ( void   ) 
TransactionId GetCurrentTransactionIdIfAny ( void   ) 
int GetCurrentTransactionNestLevel ( void   ) 
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().

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   ) 
TransactionId GetTopTransactionIdIfAny ( void   ) 
bool IsAbortedTransactionBlockState ( void   ) 
bool IsInTransactionChain ( bool  isTopLevel  ) 

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   ) 
bool IsTransactionBlock ( void   ) 
bool IsTransactionOrTransactionBlock ( void   ) 
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]
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 
)
void RegisterXactCallback ( XactCallback  callback,
void *  arg 
)
void ReleaseCurrentSubTransaction ( void   ) 
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   ) 
static void SetCurrentTransactionStopTimestamp ( void   )  [inline, static]
static void ShowTransactionState ( const char *  str  )  [static]
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]
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   ) 
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().

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  ) 

Variable Documentation

Definition at line 194 of file xact.c.

Referenced by PushTransaction(), and StartTransaction().

Definition at line 188 of file xact.c.

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().

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().

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().

Definition at line 249 of file xact.c.

int synchronous_commit = SYNCHRONOUS_COMMIT_ON

Definition at line 71 of file xact.c.

Referenced by AutoVacWorkerMain(), and RecordTransactionCommit().

Initial value:
 {
    0,                          
    0,                          
    NULL,                       
    0,                          
    TRANS_DEFAULT,              
    TBLOCK_DEFAULT,             
    0,                          
    0,                          
    NULL,                       
    NULL,                       
    NULL,                       
    0,                          
    0,                          
    InvalidOid,                 
    0,                          
    false,                      
    false,                      
    NULL                        
}

Definition at line 159 of file xact.c.

Definition at line 225 of file xact.c.

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 237 of file xact.c.

Definition at line 205 of file xact.c.

Referenced by GetCurrentTransactionStartTimestamp(), and StartTransaction().