LCOV - code coverage report
Current view: top level - src/backend/access/transam - xact.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 87.0 % 1846 1606
Test Date: 2026-03-24 01:16:09 Functions: 93.6 % 109 102
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * xact.c
       4              :  *    top level transaction system support routines
       5              :  *
       6              :  * See src/backend/access/transam/README for more information.
       7              :  *
       8              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       9              :  * Portions Copyright (c) 1994, Regents of the University of California
      10              :  *
      11              :  *
      12              :  * IDENTIFICATION
      13              :  *    src/backend/access/transam/xact.c
      14              :  *
      15              :  *-------------------------------------------------------------------------
      16              :  */
      17              : 
      18              : #include "postgres.h"
      19              : 
      20              : #include <time.h>
      21              : #include <unistd.h>
      22              : 
      23              : #include "access/commit_ts.h"
      24              : #include "access/multixact.h"
      25              : #include "access/parallel.h"
      26              : #include "access/subtrans.h"
      27              : #include "access/transam.h"
      28              : #include "access/twophase.h"
      29              : #include "access/xact.h"
      30              : #include "access/xlog.h"
      31              : #include "access/xloginsert.h"
      32              : #include "access/xlogrecovery.h"
      33              : #include "access/xlogutils.h"
      34              : #include "access/xlogwait.h"
      35              : #include "catalog/index.h"
      36              : #include "catalog/namespace.h"
      37              : #include "catalog/pg_enum.h"
      38              : #include "catalog/storage.h"
      39              : #include "commands/async.h"
      40              : #include "commands/tablecmds.h"
      41              : #include "commands/trigger.h"
      42              : #include "common/pg_prng.h"
      43              : #include "executor/spi.h"
      44              : #include "libpq/be-fsstubs.h"
      45              : #include "libpq/pqsignal.h"
      46              : #include "miscadmin.h"
      47              : #include "pg_trace.h"
      48              : #include "pgstat.h"
      49              : #include "replication/logical.h"
      50              : #include "replication/logicallauncher.h"
      51              : #include "replication/logicalworker.h"
      52              : #include "replication/origin.h"
      53              : #include "replication/snapbuild.h"
      54              : #include "replication/syncrep.h"
      55              : #include "storage/aio_subsys.h"
      56              : #include "storage/condition_variable.h"
      57              : #include "storage/fd.h"
      58              : #include "storage/lmgr.h"
      59              : #include "storage/md.h"
      60              : #include "storage/predicate.h"
      61              : #include "storage/proc.h"
      62              : #include "storage/procarray.h"
      63              : #include "storage/sinvaladt.h"
      64              : #include "storage/smgr.h"
      65              : #include "utils/builtins.h"
      66              : #include "utils/combocid.h"
      67              : #include "utils/guc.h"
      68              : #include "utils/inval.h"
      69              : #include "utils/memutils.h"
      70              : #include "utils/relmapper.h"
      71              : #include "utils/snapmgr.h"
      72              : #include "utils/timeout.h"
      73              : #include "utils/timestamp.h"
      74              : #include "utils/typcache.h"
      75              : #include "utils/wait_event.h"
      76              : 
      77              : /*
      78              :  *  User-tweakable parameters
      79              :  */
      80              : int         DefaultXactIsoLevel = XACT_READ_COMMITTED;
      81              : int         XactIsoLevel = XACT_READ_COMMITTED;
      82              : 
      83              : bool        DefaultXactReadOnly = false;
      84              : bool        XactReadOnly;
      85              : 
      86              : bool        DefaultXactDeferrable = false;
      87              : bool        XactDeferrable;
      88              : 
      89              : int         synchronous_commit = SYNCHRONOUS_COMMIT_ON;
      90              : 
      91              : /*
      92              :  * CheckXidAlive is a xid value pointing to a possibly ongoing (sub)
      93              :  * transaction.  Currently, it is used in logical decoding.  It's possible
      94              :  * that such transactions can get aborted while the decoding is ongoing in
      95              :  * which case we skip decoding that particular transaction.  To ensure that we
      96              :  * check whether the CheckXidAlive is aborted after fetching the tuple from
      97              :  * system tables.  We also ensure that during logical decoding we never
      98              :  * directly access the tableam or heap APIs because we are checking for the
      99              :  * concurrent aborts only in systable_* APIs.
     100              :  */
     101              : TransactionId CheckXidAlive = InvalidTransactionId;
     102              : bool        bsysscan = false;
     103              : 
     104              : /*
     105              :  * When running as a parallel worker, we place only a single
     106              :  * TransactionStateData on the parallel worker's state stack, and the XID
     107              :  * reflected there will be that of the *innermost* currently-active
     108              :  * subtransaction in the backend that initiated parallelism.  However,
     109              :  * GetTopTransactionId() and TransactionIdIsCurrentTransactionId()
     110              :  * need to return the same answers in the parallel worker as they would have
     111              :  * in the user backend, so we need some additional bookkeeping.
     112              :  *
     113              :  * XactTopFullTransactionId stores the XID of our toplevel transaction, which
     114              :  * will be the same as TopTransactionStateData.fullTransactionId in an
     115              :  * ordinary backend; but in a parallel backend, which does not have the entire
     116              :  * transaction state, it will instead be copied from the backend that started
     117              :  * the parallel operation.
     118              :  *
     119              :  * nParallelCurrentXids will be 0 and ParallelCurrentXids NULL in an ordinary
     120              :  * backend, but in a parallel backend, nParallelCurrentXids will contain the
     121              :  * number of XIDs that need to be considered current, and ParallelCurrentXids
     122              :  * will contain the XIDs themselves.  This includes all XIDs that were current
     123              :  * or sub-committed in the parent at the time the parallel operation began.
     124              :  * The XIDs are stored sorted in numerical order (not logical order) to make
     125              :  * lookups as fast as possible.
     126              :  */
     127              : static FullTransactionId XactTopFullTransactionId = {InvalidTransactionId};
     128              : static int  nParallelCurrentXids = 0;
     129              : static TransactionId *ParallelCurrentXids;
     130              : 
     131              : /*
     132              :  * Miscellaneous flag bits to record events which occur on the top level
     133              :  * transaction. These flags are only persisted in MyXactFlags and are intended
     134              :  * so we remember to do certain things later on in the transaction. This is
     135              :  * globally accessible, so can be set from anywhere in the code that requires
     136              :  * recording flags.
     137              :  */
     138              : int         MyXactFlags;
     139              : 
     140              : /*
     141              :  *  transaction states - transaction state from server perspective
     142              :  */
     143              : typedef enum TransState
     144              : {
     145              :     TRANS_DEFAULT,              /* idle */
     146              :     TRANS_START,                /* transaction starting */
     147              :     TRANS_INPROGRESS,           /* inside a valid transaction */
     148              :     TRANS_COMMIT,               /* commit in progress */
     149              :     TRANS_ABORT,                /* abort in progress */
     150              :     TRANS_PREPARE,              /* prepare in progress */
     151              : } TransState;
     152              : 
     153              : /*
     154              :  *  transaction block states - transaction state of client queries
     155              :  *
     156              :  * Note: the subtransaction states are used only for non-topmost
     157              :  * transactions; the others appear only in the topmost transaction.
     158              :  */
     159              : typedef enum TBlockState
     160              : {
     161              :     /* not-in-transaction-block states */
     162              :     TBLOCK_DEFAULT,             /* idle */
     163              :     TBLOCK_STARTED,             /* running single-query transaction */
     164              : 
     165              :     /* transaction block states */
     166              :     TBLOCK_BEGIN,               /* starting transaction block */
     167              :     TBLOCK_INPROGRESS,          /* live transaction */
     168              :     TBLOCK_IMPLICIT_INPROGRESS, /* live transaction after implicit BEGIN */
     169              :     TBLOCK_PARALLEL_INPROGRESS, /* live transaction inside parallel worker */
     170              :     TBLOCK_END,                 /* COMMIT received */
     171              :     TBLOCK_ABORT,               /* failed xact, awaiting ROLLBACK */
     172              :     TBLOCK_ABORT_END,           /* failed xact, ROLLBACK received */
     173              :     TBLOCK_ABORT_PENDING,       /* live xact, ROLLBACK received */
     174              :     TBLOCK_PREPARE,             /* live xact, PREPARE received */
     175              : 
     176              :     /* subtransaction states */
     177              :     TBLOCK_SUBBEGIN,            /* starting a subtransaction */
     178              :     TBLOCK_SUBINPROGRESS,       /* live subtransaction */
     179              :     TBLOCK_SUBRELEASE,          /* RELEASE received */
     180              :     TBLOCK_SUBCOMMIT,           /* COMMIT received while TBLOCK_SUBINPROGRESS */
     181              :     TBLOCK_SUBABORT,            /* failed subxact, awaiting ROLLBACK */
     182              :     TBLOCK_SUBABORT_END,        /* failed subxact, ROLLBACK received */
     183              :     TBLOCK_SUBABORT_PENDING,    /* live subxact, ROLLBACK received */
     184              :     TBLOCK_SUBRESTART,          /* live subxact, ROLLBACK TO received */
     185              :     TBLOCK_SUBABORT_RESTART,    /* failed subxact, ROLLBACK TO received */
     186              : } TBlockState;
     187              : 
     188              : /*
     189              :  *  transaction state structure
     190              :  *
     191              :  * Note: parallelModeLevel counts the number of unmatched EnterParallelMode
     192              :  * calls done at this transaction level.  parallelChildXact is true if any
     193              :  * upper transaction level has nonzero parallelModeLevel.
     194              :  */
     195              : typedef struct TransactionStateData
     196              : {
     197              :     FullTransactionId fullTransactionId;    /* my FullTransactionId */
     198              :     SubTransactionId subTransactionId;  /* my subxact ID */
     199              :     char       *name;           /* savepoint name, if any */
     200              :     int         savepointLevel; /* savepoint level */
     201              :     TransState  state;          /* low-level state */
     202              :     TBlockState blockState;     /* high-level state */
     203              :     int         nestingLevel;   /* transaction nesting depth */
     204              :     int         gucNestLevel;   /* GUC context nesting depth */
     205              :     MemoryContext curTransactionContext;    /* my xact-lifetime context */
     206              :     ResourceOwner curTransactionOwner;  /* my query resources */
     207              :     MemoryContext priorContext; /* CurrentMemoryContext before xact started */
     208              :     TransactionId *childXids;   /* subcommitted child XIDs, in XID order */
     209              :     int         nChildXids;     /* # of subcommitted child XIDs */
     210              :     int         maxChildXids;   /* allocated size of childXids[] */
     211              :     Oid         prevUser;       /* previous CurrentUserId setting */
     212              :     int         prevSecContext; /* previous SecurityRestrictionContext */
     213              :     bool        prevXactReadOnly;   /* entry-time xact r/o state */
     214              :     bool        startedInRecovery;  /* did we start in recovery? */
     215              :     bool        didLogXid;      /* has xid been included in WAL record? */
     216              :     int         parallelModeLevel;  /* Enter/ExitParallelMode counter */
     217              :     bool        parallelChildXact;  /* is any parent transaction parallel? */
     218              :     bool        chain;          /* start a new block after this one */
     219              :     bool        topXidLogged;   /* for a subxact: is top-level XID logged? */
     220              :     struct TransactionStateData *parent;    /* back link to parent */
     221              : } TransactionStateData;
     222              : 
     223              : typedef TransactionStateData *TransactionState;
     224              : 
     225              : /*
     226              :  * Serialized representation used to transmit transaction state to parallel
     227              :  * workers through shared memory.
     228              :  */
     229              : typedef struct SerializedTransactionState
     230              : {
     231              :     int         xactIsoLevel;
     232              :     bool        xactDeferrable;
     233              :     FullTransactionId topFullTransactionId;
     234              :     FullTransactionId currentFullTransactionId;
     235              :     CommandId   currentCommandId;
     236              :     int         nParallelCurrentXids;
     237              :     TransactionId parallelCurrentXids[FLEXIBLE_ARRAY_MEMBER];
     238              : } SerializedTransactionState;
     239              : 
     240              : /* The size of SerializedTransactionState, not including the final array. */
     241              : #define SerializedTransactionStateHeaderSize \
     242              :     offsetof(SerializedTransactionState, parallelCurrentXids)
     243              : 
     244              : /*
     245              :  * CurrentTransactionState always points to the current transaction state
     246              :  * block.  It will point to TopTransactionStateData when not in a
     247              :  * transaction at all, or when in a top-level transaction.
     248              :  */
     249              : static TransactionStateData TopTransactionStateData = {
     250              :     .state = TRANS_DEFAULT,
     251              :     .blockState = TBLOCK_DEFAULT,
     252              :     .topXidLogged = false,
     253              : };
     254              : 
     255              : /*
     256              :  * unreportedXids holds XIDs of all subtransactions that have not yet been
     257              :  * reported in an XLOG_XACT_ASSIGNMENT record.
     258              :  */
     259              : static int  nUnreportedXids;
     260              : static TransactionId unreportedXids[PGPROC_MAX_CACHED_SUBXIDS];
     261              : 
     262              : static TransactionState CurrentTransactionState = &TopTransactionStateData;
     263              : 
     264              : /*
     265              :  * The subtransaction ID and command ID assignment counters are global
     266              :  * to a whole transaction, so we do not keep them in the state stack.
     267              :  */
     268              : static SubTransactionId currentSubTransactionId;
     269              : static CommandId currentCommandId;
     270              : static bool currentCommandIdUsed;
     271              : 
     272              : /*
     273              :  * xactStartTimestamp is the value of transaction_timestamp().
     274              :  * stmtStartTimestamp is the value of statement_timestamp().
     275              :  * xactStopTimestamp is the time at which we log a commit / abort WAL record,
     276              :  * or if that was skipped, the time of the first subsequent
     277              :  * GetCurrentTransactionStopTimestamp() call.
     278              :  *
     279              :  * These do not change as we enter and exit subtransactions, so we don't
     280              :  * keep them inside the TransactionState stack.
     281              :  */
     282              : static TimestampTz xactStartTimestamp;
     283              : static TimestampTz stmtStartTimestamp;
     284              : static TimestampTz xactStopTimestamp;
     285              : 
     286              : /*
     287              :  * GID to be used for preparing the current transaction.  This is also
     288              :  * global to a whole transaction, so we don't keep it in the state stack.
     289              :  */
     290              : static char *prepareGID;
     291              : 
     292              : /*
     293              :  * Some commands want to force synchronous commit.
     294              :  */
     295              : static bool forceSyncCommit = false;
     296              : 
     297              : /* Flag for logging statements in a transaction. */
     298              : bool        xact_is_sampled = false;
     299              : 
     300              : /*
     301              :  * Private context for transaction-abort work --- we reserve space for this
     302              :  * at startup to ensure that AbortTransaction and AbortSubTransaction can work
     303              :  * when we've run out of memory.
     304              :  */
     305              : static MemoryContext TransactionAbortContext = NULL;
     306              : 
     307              : /*
     308              :  * List of add-on start- and end-of-xact callbacks
     309              :  */
     310              : typedef struct XactCallbackItem
     311              : {
     312              :     struct XactCallbackItem *next;
     313              :     XactCallback callback;
     314              :     void       *arg;
     315              : } XactCallbackItem;
     316              : 
     317              : static XactCallbackItem *Xact_callbacks = NULL;
     318              : 
     319              : /*
     320              :  * List of add-on start- and end-of-subxact callbacks
     321              :  */
     322              : typedef struct SubXactCallbackItem
     323              : {
     324              :     struct SubXactCallbackItem *next;
     325              :     SubXactCallback callback;
     326              :     void       *arg;
     327              : } SubXactCallbackItem;
     328              : 
     329              : static SubXactCallbackItem *SubXact_callbacks = NULL;
     330              : 
     331              : 
     332              : /* local function prototypes */
     333              : static void AssignTransactionId(TransactionState s);
     334              : static void AbortTransaction(void);
     335              : static void AtAbort_Memory(void);
     336              : static void AtCleanup_Memory(void);
     337              : static void AtAbort_ResourceOwner(void);
     338              : static void AtCCI_LocalCache(void);
     339              : static void AtCommit_Memory(void);
     340              : static void AtStart_Cache(void);
     341              : static void AtStart_Memory(void);
     342              : static void AtStart_ResourceOwner(void);
     343              : static void CallXactCallbacks(XactEvent event);
     344              : static void CallSubXactCallbacks(SubXactEvent event,
     345              :                                  SubTransactionId mySubid,
     346              :                                  SubTransactionId parentSubid);
     347              : static void CleanupTransaction(void);
     348              : static void CheckTransactionBlock(bool isTopLevel, bool throwError,
     349              :                                   const char *stmtType);
     350              : static void CommitTransaction(void);
     351              : static TransactionId RecordTransactionAbort(bool isSubXact);
     352              : static void StartTransaction(void);
     353              : 
     354              : static bool CommitTransactionCommandInternal(void);
     355              : static bool AbortCurrentTransactionInternal(void);
     356              : 
     357              : static void StartSubTransaction(void);
     358              : static void CommitSubTransaction(void);
     359              : static void AbortSubTransaction(void);
     360              : static void CleanupSubTransaction(void);
     361              : static void PushTransaction(void);
     362              : static void PopTransaction(void);
     363              : 
     364              : static void AtSubAbort_Memory(void);
     365              : static void AtSubCleanup_Memory(void);
     366              : static void AtSubAbort_ResourceOwner(void);
     367              : static void AtSubCommit_Memory(void);
     368              : static void AtSubStart_Memory(void);
     369              : static void AtSubStart_ResourceOwner(void);
     370              : 
     371              : static void ShowTransactionState(const char *str);
     372              : static void ShowTransactionStateRec(const char *str, TransactionState s);
     373              : static const char *BlockStateAsString(TBlockState blockState);
     374              : static const char *TransStateAsString(TransState state);
     375              : 
     376              : 
     377              : /* ----------------------------------------------------------------
     378              :  *  transaction state accessors
     379              :  * ----------------------------------------------------------------
     380              :  */
     381              : 
     382              : /*
     383              :  *  IsTransactionState
     384              :  *
     385              :  *  This returns true if we are inside a valid transaction; that is,
     386              :  *  it is safe to initiate database access, take heavyweight locks, etc.
     387              :  */
     388              : bool
     389      1150855 : IsTransactionState(void)
     390              : {
     391      1150855 :     TransactionState s = CurrentTransactionState;
     392              : 
     393              :     /*
     394              :      * TRANS_DEFAULT and TRANS_ABORT are obviously unsafe states.  However, we
     395              :      * also reject the startup/shutdown states TRANS_START, TRANS_COMMIT,
     396              :      * TRANS_PREPARE since it might be too soon or too late within those
     397              :      * transition states to do anything interesting.  Hence, the only "valid"
     398              :      * state is TRANS_INPROGRESS.
     399              :      */
     400      1150855 :     return (s->state == TRANS_INPROGRESS);
     401              : }
     402              : 
     403              : /*
     404              :  *  IsAbortedTransactionBlockState
     405              :  *
     406              :  *  This returns true if we are within an aborted transaction block.
     407              :  */
     408              : bool
     409       935159 : IsAbortedTransactionBlockState(void)
     410              : {
     411       935159 :     TransactionState s = CurrentTransactionState;
     412              : 
     413       935159 :     if (s->blockState == TBLOCK_ABORT ||
     414       933293 :         s->blockState == TBLOCK_SUBABORT)
     415         2258 :         return true;
     416              : 
     417       932901 :     return false;
     418              : }
     419              : 
     420              : 
     421              : /*
     422              :  *  GetTopTransactionId
     423              :  *
     424              :  * This will return the XID of the main transaction, assigning one if
     425              :  * it's not yet set.  Be careful to call this only inside a valid xact.
     426              :  */
     427              : TransactionId
     428        31072 : GetTopTransactionId(void)
     429              : {
     430        31072 :     if (!FullTransactionIdIsValid(XactTopFullTransactionId))
     431          707 :         AssignTransactionId(&TopTransactionStateData);
     432        31072 :     return XidFromFullTransactionId(XactTopFullTransactionId);
     433              : }
     434              : 
     435              : /*
     436              :  *  GetTopTransactionIdIfAny
     437              :  *
     438              :  * This will return the XID of the main transaction, if one is assigned.
     439              :  * It will return InvalidTransactionId if we are not currently inside a
     440              :  * transaction, or inside a transaction that hasn't yet been assigned an XID.
     441              :  */
     442              : TransactionId
     443     59903201 : GetTopTransactionIdIfAny(void)
     444              : {
     445     59903201 :     return XidFromFullTransactionId(XactTopFullTransactionId);
     446              : }
     447              : 
     448              : /*
     449              :  *  GetCurrentTransactionId
     450              :  *
     451              :  * This will return the XID of the current transaction (main or sub
     452              :  * transaction), assigning one if it's not yet set.  Be careful to call this
     453              :  * only inside a valid xact.
     454              :  */
     455              : TransactionId
     456     13168933 : GetCurrentTransactionId(void)
     457              : {
     458     13168933 :     TransactionState s = CurrentTransactionState;
     459              : 
     460     13168933 :     if (!FullTransactionIdIsValid(s->fullTransactionId))
     461       160062 :         AssignTransactionId(s);
     462     13168927 :     return XidFromFullTransactionId(s->fullTransactionId);
     463              : }
     464              : 
     465              : /*
     466              :  *  GetCurrentTransactionIdIfAny
     467              :  *
     468              :  * This will return the XID of the current sub xact, if one is assigned.
     469              :  * It will return InvalidTransactionId if we are not currently inside a
     470              :  * transaction, or inside a transaction that hasn't been assigned an XID yet.
     471              :  */
     472              : TransactionId
     473     18260689 : GetCurrentTransactionIdIfAny(void)
     474              : {
     475     18260689 :     return XidFromFullTransactionId(CurrentTransactionState->fullTransactionId);
     476              : }
     477              : 
     478              : /*
     479              :  *  GetTopFullTransactionId
     480              :  *
     481              :  * This will return the FullTransactionId of the main transaction, assigning
     482              :  * one if it's not yet set.  Be careful to call this only inside a valid xact.
     483              :  */
     484              : FullTransactionId
     485         3168 : GetTopFullTransactionId(void)
     486              : {
     487         3168 :     if (!FullTransactionIdIsValid(XactTopFullTransactionId))
     488         2104 :         AssignTransactionId(&TopTransactionStateData);
     489         3168 :     return XactTopFullTransactionId;
     490              : }
     491              : 
     492              : /*
     493              :  *  GetTopFullTransactionIdIfAny
     494              :  *
     495              :  * This will return the FullTransactionId of the main transaction, if one is
     496              :  * assigned.  It will return InvalidFullTransactionId if we are not currently
     497              :  * inside a transaction, or inside a transaction that hasn't yet been assigned
     498              :  * one.
     499              :  */
     500              : FullTransactionId
     501           16 : GetTopFullTransactionIdIfAny(void)
     502              : {
     503           16 :     return XactTopFullTransactionId;
     504              : }
     505              : 
     506              : /*
     507              :  *  GetCurrentFullTransactionId
     508              :  *
     509              :  * This will return the FullTransactionId of the current transaction (main or
     510              :  * sub transaction), assigning one if it's not yet set.  Be careful to call
     511              :  * this only inside a valid xact.
     512              :  */
     513              : FullTransactionId
     514          386 : GetCurrentFullTransactionId(void)
     515              : {
     516          386 :     TransactionState s = CurrentTransactionState;
     517              : 
     518          386 :     if (!FullTransactionIdIsValid(s->fullTransactionId))
     519           16 :         AssignTransactionId(s);
     520          386 :     return s->fullTransactionId;
     521              : }
     522              : 
     523              : /*
     524              :  *  GetCurrentFullTransactionIdIfAny
     525              :  *
     526              :  * This will return the FullTransactionId of the current sub xact, if one is
     527              :  * assigned.  It will return InvalidFullTransactionId if we are not currently
     528              :  * inside a transaction, or inside a transaction that hasn't been assigned one
     529              :  * yet.
     530              :  */
     531              : FullTransactionId
     532            0 : GetCurrentFullTransactionIdIfAny(void)
     533              : {
     534            0 :     return CurrentTransactionState->fullTransactionId;
     535              : }
     536              : 
     537              : /*
     538              :  *  MarkCurrentTransactionIdLoggedIfAny
     539              :  *
     540              :  * Remember that the current xid - if it is assigned - now has been wal logged.
     541              :  */
     542              : void
     543     18209050 : MarkCurrentTransactionIdLoggedIfAny(void)
     544              : {
     545     18209050 :     if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId))
     546     17905608 :         CurrentTransactionState->didLogXid = true;
     547     18209050 : }
     548              : 
     549              : /*
     550              :  * IsSubxactTopXidLogPending
     551              :  *
     552              :  * This is used to decide whether we need to WAL log the top-level XID for
     553              :  * operation in a subtransaction.  We require that for logical decoding, see
     554              :  * LogicalDecodingProcessRecord.
     555              :  *
     556              :  * This returns true if effective_wal_level is logical and we are inside
     557              :  * a valid subtransaction, for which the assignment was not yet written to
     558              :  * any WAL record.
     559              :  */
     560              : bool
     561     18217591 : IsSubxactTopXidLogPending(void)
     562              : {
     563              :     /* check whether it is already logged */
     564     18217591 :     if (CurrentTransactionState->topXidLogged)
     565       102127 :         return false;
     566              : 
     567              :     /* effective_wal_level has to be logical */
     568     18115464 :     if (!XLogLogicalInfoActive())
     569     17571913 :         return false;
     570              : 
     571              :     /* we need to be in a transaction state */
     572       543551 :     if (!IsTransactionState())
     573         4176 :         return false;
     574              : 
     575              :     /* it has to be a subtransaction */
     576       539375 :     if (!IsSubTransaction())
     577       539144 :         return false;
     578              : 
     579              :     /* the subtransaction has to have a XID assigned */
     580          231 :     if (!TransactionIdIsValid(GetCurrentTransactionIdIfAny()))
     581           10 :         return false;
     582              : 
     583          221 :     return true;
     584              : }
     585              : 
     586              : /*
     587              :  * MarkSubxactTopXidLogged
     588              :  *
     589              :  * Remember that the top transaction id for the current subtransaction is WAL
     590              :  * logged now.
     591              :  */
     592              : void
     593          219 : MarkSubxactTopXidLogged(void)
     594              : {
     595              :     Assert(IsSubxactTopXidLogPending());
     596              : 
     597          219 :     CurrentTransactionState->topXidLogged = true;
     598          219 : }
     599              : 
     600              : /*
     601              :  *  GetStableLatestTransactionId
     602              :  *
     603              :  * Get the transaction's XID if it has one, else read the next-to-be-assigned
     604              :  * XID.  Once we have a value, return that same value for the remainder of the
     605              :  * current transaction.  This is meant to provide the reference point for the
     606              :  * age(xid) function, but might be useful for other maintenance tasks as well.
     607              :  */
     608              : TransactionId
     609          165 : GetStableLatestTransactionId(void)
     610              : {
     611              :     static LocalTransactionId lxid = InvalidLocalTransactionId;
     612              :     static TransactionId stablexid = InvalidTransactionId;
     613              : 
     614          165 :     if (lxid != MyProc->vxid.lxid)
     615              :     {
     616           17 :         lxid = MyProc->vxid.lxid;
     617           17 :         stablexid = GetTopTransactionIdIfAny();
     618           17 :         if (!TransactionIdIsValid(stablexid))
     619           17 :             stablexid = ReadNextTransactionId();
     620              :     }
     621              : 
     622              :     Assert(TransactionIdIsValid(stablexid));
     623              : 
     624          165 :     return stablexid;
     625              : }
     626              : 
     627              : /*
     628              :  * AssignTransactionId
     629              :  *
     630              :  * Assigns a new permanent FullTransactionId to the given TransactionState.
     631              :  * We do not assign XIDs to transactions until/unless this is called.
     632              :  * Also, any parent TransactionStates that don't yet have XIDs are assigned
     633              :  * one; this maintains the invariant that a child transaction has an XID
     634              :  * following its parent's.
     635              :  */
     636              : static void
     637       164104 : AssignTransactionId(TransactionState s)
     638              : {
     639       164104 :     bool        isSubXact = (s->parent != NULL);
     640              :     ResourceOwner currentOwner;
     641       164104 :     bool        log_unknown_top = false;
     642              : 
     643              :     /* Assert that caller didn't screw up */
     644              :     Assert(!FullTransactionIdIsValid(s->fullTransactionId));
     645              :     Assert(s->state == TRANS_INPROGRESS);
     646              : 
     647              :     /*
     648              :      * Workers synchronize transaction state at the beginning of each parallel
     649              :      * operation, so we can't account for new XIDs at this point.
     650              :      */
     651       164104 :     if (IsInParallelMode() || IsParallelWorker())
     652            0 :         ereport(ERROR,
     653              :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
     654              :                  errmsg("cannot assign transaction IDs during a parallel operation")));
     655              : 
     656              :     /*
     657              :      * Ensure parent(s) have XIDs, so that a child always has an XID later
     658              :      * than its parent.  Mustn't recurse here, or we might get a stack
     659              :      * overflow if we're at the bottom of a huge stack of subtransactions none
     660              :      * of which have XIDs yet.
     661              :      */
     662       164104 :     if (isSubXact && !FullTransactionIdIsValid(s->parent->fullTransactionId))
     663              :     {
     664          622 :         TransactionState p = s->parent;
     665              :         TransactionState *parents;
     666          622 :         size_t      parentOffset = 0;
     667              : 
     668          622 :         parents = palloc_array(TransactionState, s->nestingLevel);
     669         1837 :         while (p != NULL && !FullTransactionIdIsValid(p->fullTransactionId))
     670              :         {
     671         1215 :             parents[parentOffset++] = p;
     672         1215 :             p = p->parent;
     673              :         }
     674              : 
     675              :         /*
     676              :          * This is technically a recursive call, but the recursion will never
     677              :          * be more than one layer deep.
     678              :          */
     679         1837 :         while (parentOffset != 0)
     680         1215 :             AssignTransactionId(parents[--parentOffset]);
     681              : 
     682          622 :         pfree(parents);
     683              :     }
     684              : 
     685              :     /*
     686              :      * When effective_wal_level is logical, guarantee that a subtransaction's
     687              :      * xid can only be seen in the WAL stream if its toplevel xid has been
     688              :      * logged before. If necessary we log an xact_assignment record with fewer
     689              :      * than PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't
     690              :      * set for a transaction even though it appears in a WAL record, we just
     691              :      * might superfluously log something. That can happen when an xid is
     692              :      * included somewhere inside a wal record, but not in XLogRecord->xl_xid,
     693              :      * like in xl_standby_locks.
     694              :      */
     695       164104 :     if (isSubXact && XLogLogicalInfoActive() &&
     696          300 :         !TopTransactionStateData.didLogXid)
     697           24 :         log_unknown_top = true;
     698              : 
     699              :     /*
     700              :      * Generate a new FullTransactionId and record its xid in PGPROC and
     701              :      * pg_subtrans.
     702              :      *
     703              :      * NB: we must make the subtrans entry BEFORE the Xid appears anywhere in
     704              :      * shared storage other than PGPROC; because if there's no room for it in
     705              :      * PGPROC, the subtrans entry is needed to ensure that other backends see
     706              :      * the Xid as "running".  See GetNewTransactionId.
     707              :      */
     708       164104 :     s->fullTransactionId = GetNewTransactionId(isSubXact);
     709       164098 :     if (!isSubXact)
     710       159521 :         XactTopFullTransactionId = s->fullTransactionId;
     711              : 
     712       164098 :     if (isSubXact)
     713         4577 :         SubTransSetParent(XidFromFullTransactionId(s->fullTransactionId),
     714         4577 :                           XidFromFullTransactionId(s->parent->fullTransactionId));
     715              : 
     716              :     /*
     717              :      * If it's a top-level transaction, the predicate locking system needs to
     718              :      * be told about it too.
     719              :      */
     720       164098 :     if (!isSubXact)
     721       159521 :         RegisterPredicateLockingXid(XidFromFullTransactionId(s->fullTransactionId));
     722              : 
     723              :     /*
     724              :      * Acquire lock on the transaction XID.  (We assume this cannot block.) We
     725              :      * have to ensure that the lock is assigned to the transaction's own
     726              :      * ResourceOwner.
     727              :      */
     728       164098 :     currentOwner = CurrentResourceOwner;
     729       164098 :     CurrentResourceOwner = s->curTransactionOwner;
     730              : 
     731       164098 :     XactLockTableInsert(XidFromFullTransactionId(s->fullTransactionId));
     732              : 
     733       164098 :     CurrentResourceOwner = currentOwner;
     734              : 
     735              :     /*
     736              :      * Every PGPROC_MAX_CACHED_SUBXIDS assigned transaction ids within each
     737              :      * top-level transaction we issue a WAL record for the assignment. We
     738              :      * include the top-level xid and all the subxids that have not yet been
     739              :      * reported using XLOG_XACT_ASSIGNMENT records.
     740              :      *
     741              :      * This is required to limit the amount of shared memory required in a hot
     742              :      * standby server to keep track of in-progress XIDs. See notes for
     743              :      * RecordKnownAssignedTransactionIds().
     744              :      *
     745              :      * We don't keep track of the immediate parent of each subxid, only the
     746              :      * top-level transaction that each subxact belongs to. This is correct in
     747              :      * recovery only because aborted subtransactions are separately WAL
     748              :      * logged.
     749              :      *
     750              :      * This is correct even for the case where several levels above us didn't
     751              :      * have an xid assigned as we recursed up to them beforehand.
     752              :      */
     753       164098 :     if (isSubXact && XLogStandbyInfoActive())
     754              :     {
     755         4068 :         unreportedXids[nUnreportedXids] = XidFromFullTransactionId(s->fullTransactionId);
     756         4068 :         nUnreportedXids++;
     757              : 
     758              :         /*
     759              :          * ensure this test matches similar one in
     760              :          * RecoverPreparedTransactions()
     761              :          */
     762         4068 :         if (nUnreportedXids >= PGPROC_MAX_CACHED_SUBXIDS ||
     763              :             log_unknown_top)
     764              :         {
     765              :             xl_xact_assignment xlrec;
     766              : 
     767              :             /*
     768              :              * xtop is always set by now because we recurse up transaction
     769              :              * stack to the highest unassigned xid and then come back down
     770              :              */
     771           67 :             xlrec.xtop = GetTopTransactionId();
     772              :             Assert(TransactionIdIsValid(xlrec.xtop));
     773           67 :             xlrec.nsubxacts = nUnreportedXids;
     774              : 
     775           67 :             XLogBeginInsert();
     776           67 :             XLogRegisterData(&xlrec, MinSizeOfXactAssignment);
     777           67 :             XLogRegisterData(unreportedXids,
     778              :                              nUnreportedXids * sizeof(TransactionId));
     779              : 
     780           67 :             (void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
     781              : 
     782           67 :             nUnreportedXids = 0;
     783              :             /* mark top, not current xact as having been logged */
     784           67 :             TopTransactionStateData.didLogXid = true;
     785              :         }
     786              :     }
     787       164098 : }
     788              : 
     789              : /*
     790              :  *  GetCurrentSubTransactionId
     791              :  */
     792              : SubTransactionId
     793     10493552 : GetCurrentSubTransactionId(void)
     794              : {
     795     10493552 :     TransactionState s = CurrentTransactionState;
     796              : 
     797     10493552 :     return s->subTransactionId;
     798              : }
     799              : 
     800              : /*
     801              :  *  SubTransactionIsActive
     802              :  *
     803              :  * Test if the specified subxact ID is still active.  Note caller is
     804              :  * responsible for checking whether this ID is relevant to the current xact.
     805              :  */
     806              : bool
     807            0 : SubTransactionIsActive(SubTransactionId subxid)
     808              : {
     809              :     TransactionState s;
     810              : 
     811            0 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
     812              :     {
     813            0 :         if (s->state == TRANS_ABORT)
     814            0 :             continue;
     815            0 :         if (s->subTransactionId == subxid)
     816            0 :             return true;
     817              :     }
     818            0 :     return false;
     819              : }
     820              : 
     821              : 
     822              : /*
     823              :  *  GetCurrentCommandId
     824              :  *
     825              :  * "used" must be true if the caller intends to use the command ID to mark
     826              :  * inserted/updated/deleted tuples.  false means the ID is being fetched
     827              :  * for read-only purposes (ie, as a snapshot validity cutoff).  See
     828              :  * CommandCounterIncrement() for discussion.
     829              :  */
     830              : CommandId
     831      8266079 : GetCurrentCommandId(bool used)
     832              : {
     833              :     /* this is global to a transaction, not subtransaction-local */
     834      8266079 :     if (used)
     835              :     {
     836              :         /*
     837              :          * Forbid setting currentCommandIdUsed in a parallel worker, because
     838              :          * we have no provision for communicating this back to the leader.  We
     839              :          * could relax this restriction when currentCommandIdUsed was already
     840              :          * true at the start of the parallel operation.
     841              :          */
     842      4566994 :         if (IsParallelWorker())
     843            0 :             ereport(ERROR,
     844              :                     (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
     845              :                      errmsg("cannot modify data in a parallel worker")));
     846              : 
     847      4566994 :         currentCommandIdUsed = true;
     848              :     }
     849      8266079 :     return currentCommandId;
     850              : }
     851              : 
     852              : /*
     853              :  *  SetParallelStartTimestamps
     854              :  *
     855              :  * In a parallel worker, we should inherit the parent transaction's
     856              :  * timestamps rather than setting our own.  The parallel worker
     857              :  * infrastructure must call this to provide those values before
     858              :  * calling StartTransaction() or SetCurrentStatementStartTimestamp().
     859              :  */
     860              : void
     861         1999 : SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts)
     862              : {
     863              :     Assert(IsParallelWorker());
     864         1999 :     xactStartTimestamp = xact_ts;
     865         1999 :     stmtStartTimestamp = stmt_ts;
     866         1999 : }
     867              : 
     868              : /*
     869              :  *  GetCurrentTransactionStartTimestamp
     870              :  */
     871              : TimestampTz
     872        45111 : GetCurrentTransactionStartTimestamp(void)
     873              : {
     874        45111 :     return xactStartTimestamp;
     875              : }
     876              : 
     877              : /*
     878              :  *  GetCurrentStatementStartTimestamp
     879              :  */
     880              : TimestampTz
     881      1472983 : GetCurrentStatementStartTimestamp(void)
     882              : {
     883      1472983 :     return stmtStartTimestamp;
     884              : }
     885              : 
     886              : /*
     887              :  *  GetCurrentTransactionStopTimestamp
     888              :  *
     889              :  * If the transaction stop time hasn't already been set, which can happen if
     890              :  * we decided we don't need to log an XLOG record, set xactStopTimestamp.
     891              :  */
     892              : TimestampTz
     893      1236540 : GetCurrentTransactionStopTimestamp(void)
     894              : {
     895      1236540 :     TransactionState s PG_USED_FOR_ASSERTS_ONLY = CurrentTransactionState;
     896              : 
     897              :     /* should only be called after commit / abort processing */
     898              :     Assert(s->state == TRANS_DEFAULT ||
     899              :            s->state == TRANS_COMMIT ||
     900              :            s->state == TRANS_ABORT ||
     901              :            s->state == TRANS_PREPARE);
     902              : 
     903      1236540 :     if (xactStopTimestamp == 0)
     904       367852 :         xactStopTimestamp = GetCurrentTimestamp();
     905              : 
     906      1236540 :     return xactStopTimestamp;
     907              : }
     908              : 
     909              : /*
     910              :  *  SetCurrentStatementStartTimestamp
     911              :  *
     912              :  * In a parallel worker, this should already have been provided by a call
     913              :  * to SetParallelStartTimestamps().
     914              :  */
     915              : void
     916       730720 : SetCurrentStatementStartTimestamp(void)
     917              : {
     918       730720 :     if (!IsParallelWorker())
     919       728721 :         stmtStartTimestamp = GetCurrentTimestamp();
     920              :     else
     921              :         Assert(stmtStartTimestamp != 0);
     922       730720 : }
     923              : 
     924              : /*
     925              :  *  GetCurrentTransactionNestLevel
     926              :  *
     927              :  * Note: this will return zero when not inside any transaction, one when
     928              :  * inside a top-level transaction, etc.
     929              :  */
     930              : int
     931     22127645 : GetCurrentTransactionNestLevel(void)
     932              : {
     933     22127645 :     TransactionState s = CurrentTransactionState;
     934              : 
     935     22127645 :     return s->nestingLevel;
     936              : }
     937              : 
     938              : 
     939              : /*
     940              :  *  TransactionIdIsCurrentTransactionId
     941              :  */
     942              : bool
     943     59822927 : TransactionIdIsCurrentTransactionId(TransactionId xid)
     944              : {
     945              :     TransactionState s;
     946              : 
     947              :     /*
     948              :      * We always say that BootstrapTransactionId is "not my transaction ID"
     949              :      * even when it is (ie, during bootstrap).  Along with the fact that
     950              :      * transam.c always treats BootstrapTransactionId as already committed,
     951              :      * this causes the heapam_visibility.c routines to see all tuples as
     952              :      * committed, which is what we need during bootstrap.  (Bootstrap mode
     953              :      * only inserts tuples, it never updates or deletes them, so all tuples
     954              :      * can be presumed good immediately.)
     955              :      *
     956              :      * Likewise, InvalidTransactionId and FrozenTransactionId are certainly
     957              :      * not my transaction ID, so we can just return "false" immediately for
     958              :      * any non-normal XID.
     959              :      */
     960     59822927 :     if (!TransactionIdIsNormal(xid))
     961       665165 :         return false;
     962              : 
     963     59157762 :     if (TransactionIdEquals(xid, GetTopTransactionIdIfAny()))
     964     37237163 :         return true;
     965              : 
     966              :     /*
     967              :      * In parallel workers, the XIDs we must consider as current are stored in
     968              :      * ParallelCurrentXids rather than the transaction-state stack.  Note that
     969              :      * the XIDs in this array are sorted numerically rather than according to
     970              :      * transactionIdPrecedes order.
     971              :      */
     972     21920599 :     if (nParallelCurrentXids > 0)
     973              :     {
     974              :         int         low,
     975              :                     high;
     976              : 
     977      2505074 :         low = 0;
     978      2505074 :         high = nParallelCurrentXids - 1;
     979      9777233 :         while (low <= high)
     980              :         {
     981              :             int         middle;
     982              :             TransactionId probe;
     983              : 
     984      9655765 :             middle = low + (high - low) / 2;
     985      9655765 :             probe = ParallelCurrentXids[middle];
     986      9655765 :             if (probe == xid)
     987      2383606 :                 return true;
     988      7272159 :             else if (probe < xid)
     989      7150707 :                 low = middle + 1;
     990              :             else
     991       121452 :                 high = middle - 1;
     992              :         }
     993       121468 :         return false;
     994              :     }
     995              : 
     996              :     /*
     997              :      * We will return true for the Xid of the current subtransaction, any of
     998              :      * its subcommitted children, any of its parents, or any of their
     999              :      * previously subcommitted children.  However, a transaction being aborted
    1000              :      * is no longer "current", even though it may still have an entry on the
    1001              :      * state stack.
    1002              :      */
    1003     38791890 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    1004              :     {
    1005              :         int         low,
    1006              :                     high;
    1007              : 
    1008     19495099 :         if (s->state == TRANS_ABORT)
    1009            0 :             continue;
    1010     19495099 :         if (!FullTransactionIdIsValid(s->fullTransactionId))
    1011      9732455 :             continue;           /* it can't have any child XIDs either */
    1012      9762644 :         if (TransactionIdEquals(xid, XidFromFullTransactionId(s->fullTransactionId)))
    1013       117175 :             return true;
    1014              :         /* As the childXids array is ordered, we can use binary search */
    1015      9645469 :         low = 0;
    1016      9645469 :         high = s->nChildXids - 1;
    1017      9646367 :         while (low <= high)
    1018              :         {
    1019              :             int         middle;
    1020              :             TransactionId probe;
    1021              : 
    1022         2457 :             middle = low + (high - low) / 2;
    1023         2457 :             probe = s->childXids[middle];
    1024         2457 :             if (TransactionIdEquals(probe, xid))
    1025         1559 :                 return true;
    1026          898 :             else if (TransactionIdPrecedes(probe, xid))
    1027          803 :                 low = middle + 1;
    1028              :             else
    1029           95 :                 high = middle - 1;
    1030              :         }
    1031              :     }
    1032              : 
    1033     19296791 :     return false;
    1034              : }
    1035              : 
    1036              : /*
    1037              :  *  TransactionStartedDuringRecovery
    1038              :  *
    1039              :  * Returns true if the current transaction started while recovery was still
    1040              :  * in progress. Recovery might have ended since so RecoveryInProgress() might
    1041              :  * return false already.
    1042              :  */
    1043              : bool
    1044      9710627 : TransactionStartedDuringRecovery(void)
    1045              : {
    1046      9710627 :     return CurrentTransactionState->startedInRecovery;
    1047              : }
    1048              : 
    1049              : /*
    1050              :  *  EnterParallelMode
    1051              :  */
    1052              : void
    1053         4646 : EnterParallelMode(void)
    1054              : {
    1055         4646 :     TransactionState s = CurrentTransactionState;
    1056              : 
    1057              :     Assert(s->parallelModeLevel >= 0);
    1058              : 
    1059         4646 :     ++s->parallelModeLevel;
    1060         4646 : }
    1061              : 
    1062              : /*
    1063              :  *  ExitParallelMode
    1064              :  */
    1065              : void
    1066         2639 : ExitParallelMode(void)
    1067              : {
    1068         2639 :     TransactionState s = CurrentTransactionState;
    1069              : 
    1070              :     Assert(s->parallelModeLevel > 0);
    1071              :     Assert(s->parallelModeLevel > 1 || s->parallelChildXact ||
    1072              :            !ParallelContextActive());
    1073              : 
    1074         2639 :     --s->parallelModeLevel;
    1075         2639 : }
    1076              : 
    1077              : /*
    1078              :  *  IsInParallelMode
    1079              :  *
    1080              :  * Are we in a parallel operation, as either the leader or a worker?  Check
    1081              :  * this to prohibit operations that change backend-local state expected to
    1082              :  * match across all workers.  Mere caches usually don't require such a
    1083              :  * restriction.  State modified in a strict push/pop fashion, such as the
    1084              :  * active snapshot stack, is often fine.
    1085              :  *
    1086              :  * We say we are in parallel mode if we are in a subxact of a transaction
    1087              :  * that's initiated a parallel operation; for most purposes that context
    1088              :  * has all the same restrictions.
    1089              :  */
    1090              : bool
    1091     31059525 : IsInParallelMode(void)
    1092              : {
    1093     31059525 :     TransactionState s = CurrentTransactionState;
    1094              : 
    1095     31059525 :     return s->parallelModeLevel != 0 || s->parallelChildXact;
    1096              : }
    1097              : 
    1098              : /*
    1099              :  *  CommandCounterIncrement
    1100              :  */
    1101              : void
    1102      2068696 : CommandCounterIncrement(void)
    1103              : {
    1104              :     /*
    1105              :      * If the current value of the command counter hasn't been "used" to mark
    1106              :      * tuples, we need not increment it, since there's no need to distinguish
    1107              :      * a read-only command from others.  This helps postpone command counter
    1108              :      * overflow, and keeps no-op CommandCounterIncrement operations cheap.
    1109              :      */
    1110      2068696 :     if (currentCommandIdUsed)
    1111              :     {
    1112              :         /*
    1113              :          * Workers synchronize transaction state at the beginning of each
    1114              :          * parallel operation, so we can't account for new commands after that
    1115              :          * point.
    1116              :          */
    1117      1074258 :         if (IsInParallelMode() || IsParallelWorker())
    1118            0 :             ereport(ERROR,
    1119              :                     (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    1120              :                      errmsg("cannot start commands during a parallel operation")));
    1121              : 
    1122      1074258 :         currentCommandId += 1;
    1123      1074258 :         if (currentCommandId == InvalidCommandId)
    1124              :         {
    1125            0 :             currentCommandId -= 1;
    1126            0 :             ereport(ERROR,
    1127              :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1128              :                      errmsg("cannot have more than 2^32-2 commands in a transaction")));
    1129              :         }
    1130      1074258 :         currentCommandIdUsed = false;
    1131              : 
    1132              :         /* Propagate new command ID into static snapshots */
    1133      1074258 :         SnapshotSetCommandId(currentCommandId);
    1134              : 
    1135              :         /*
    1136              :          * Make any catalog changes done by the just-completed command visible
    1137              :          * in the local syscache.  We obviously don't need to do this after a
    1138              :          * read-only command.  (But see hacks in inval.c to make real sure we
    1139              :          * don't think a command that queued inval messages was read-only.)
    1140              :          */
    1141      1074258 :         AtCCI_LocalCache();
    1142              :     }
    1143      2068692 : }
    1144              : 
    1145              : /*
    1146              :  * ForceSyncCommit
    1147              :  *
    1148              :  * Interface routine to allow commands to force a synchronous commit of the
    1149              :  * current top-level transaction.  Currently, two-phase commit does not
    1150              :  * persist and restore this variable.  So long as all callers use
    1151              :  * PreventInTransactionBlock(), that omission has no consequences.
    1152              :  */
    1153              : void
    1154          556 : ForceSyncCommit(void)
    1155              : {
    1156          556 :     forceSyncCommit = true;
    1157          556 : }
    1158              : 
    1159              : 
    1160              : /* ----------------------------------------------------------------
    1161              :  *                      StartTransaction stuff
    1162              :  * ----------------------------------------------------------------
    1163              :  */
    1164              : 
    1165              : /*
    1166              :  *  AtStart_Cache
    1167              :  */
    1168              : static void
    1169       614843 : AtStart_Cache(void)
    1170              : {
    1171       614843 :     AcceptInvalidationMessages();
    1172       614843 : }
    1173              : 
    1174              : /*
    1175              :  *  AtStart_Memory
    1176              :  */
    1177              : static void
    1178       614843 : AtStart_Memory(void)
    1179              : {
    1180       614843 :     TransactionState s = CurrentTransactionState;
    1181              : 
    1182              :     /*
    1183              :      * Remember the memory context that was active prior to transaction start.
    1184              :      */
    1185       614843 :     s->priorContext = CurrentMemoryContext;
    1186              : 
    1187              :     /*
    1188              :      * If this is the first time through, create a private context for
    1189              :      * AbortTransaction to work in.  By reserving some space now, we can
    1190              :      * insulate AbortTransaction from out-of-memory scenarios.  Like
    1191              :      * ErrorContext, we set it up with slow growth rate and a nonzero minimum
    1192              :      * size, so that space will be reserved immediately.
    1193              :      */
    1194       614843 :     if (TransactionAbortContext == NULL)
    1195        19242 :         TransactionAbortContext =
    1196        19242 :             AllocSetContextCreate(TopMemoryContext,
    1197              :                                   "TransactionAbortContext",
    1198              :                                   32 * 1024,
    1199              :                                   32 * 1024,
    1200              :                                   32 * 1024);
    1201              : 
    1202              :     /*
    1203              :      * Likewise, if this is the first time through, create a top-level context
    1204              :      * for transaction-local data.  This context will be reset at transaction
    1205              :      * end, and then re-used in later transactions.
    1206              :      */
    1207       614843 :     if (TopTransactionContext == NULL)
    1208        19242 :         TopTransactionContext =
    1209        19242 :             AllocSetContextCreate(TopMemoryContext,
    1210              :                                   "TopTransactionContext",
    1211              :                                   ALLOCSET_DEFAULT_SIZES);
    1212              : 
    1213              :     /*
    1214              :      * In a top-level transaction, CurTransactionContext is the same as
    1215              :      * TopTransactionContext.
    1216              :      */
    1217       614843 :     CurTransactionContext = TopTransactionContext;
    1218       614843 :     s->curTransactionContext = CurTransactionContext;
    1219              : 
    1220              :     /* Make the CurTransactionContext active. */
    1221       614843 :     MemoryContextSwitchTo(CurTransactionContext);
    1222       614843 : }
    1223              : 
    1224              : /*
    1225              :  *  AtStart_ResourceOwner
    1226              :  */
    1227              : static void
    1228       614843 : AtStart_ResourceOwner(void)
    1229              : {
    1230       614843 :     TransactionState s = CurrentTransactionState;
    1231              : 
    1232              :     /*
    1233              :      * We shouldn't have a transaction resource owner already.
    1234              :      */
    1235              :     Assert(TopTransactionResourceOwner == NULL);
    1236              : 
    1237              :     /*
    1238              :      * Create a toplevel resource owner for the transaction.
    1239              :      */
    1240       614843 :     s->curTransactionOwner = ResourceOwnerCreate(NULL, "TopTransaction");
    1241              : 
    1242       614843 :     TopTransactionResourceOwner = s->curTransactionOwner;
    1243       614843 :     CurTransactionResourceOwner = s->curTransactionOwner;
    1244       614843 :     CurrentResourceOwner = s->curTransactionOwner;
    1245       614843 : }
    1246              : 
    1247              : /* ----------------------------------------------------------------
    1248              :  *                      StartSubTransaction stuff
    1249              :  * ----------------------------------------------------------------
    1250              :  */
    1251              : 
    1252              : /*
    1253              :  * AtSubStart_Memory
    1254              :  */
    1255              : static void
    1256        11797 : AtSubStart_Memory(void)
    1257              : {
    1258        11797 :     TransactionState s = CurrentTransactionState;
    1259              : 
    1260              :     Assert(CurTransactionContext != NULL);
    1261              : 
    1262              :     /*
    1263              :      * Remember the context that was active prior to subtransaction start.
    1264              :      */
    1265        11797 :     s->priorContext = CurrentMemoryContext;
    1266              : 
    1267              :     /*
    1268              :      * Create a CurTransactionContext, which will be used to hold data that
    1269              :      * survives subtransaction commit but disappears on subtransaction abort.
    1270              :      * We make it a child of the immediate parent's CurTransactionContext.
    1271              :      */
    1272        11797 :     CurTransactionContext = AllocSetContextCreate(CurTransactionContext,
    1273              :                                                   "CurTransactionContext",
    1274              :                                                   ALLOCSET_DEFAULT_SIZES);
    1275        11797 :     s->curTransactionContext = CurTransactionContext;
    1276              : 
    1277              :     /* Make the CurTransactionContext active. */
    1278        11797 :     MemoryContextSwitchTo(CurTransactionContext);
    1279        11797 : }
    1280              : 
    1281              : /*
    1282              :  * AtSubStart_ResourceOwner
    1283              :  */
    1284              : static void
    1285        11797 : AtSubStart_ResourceOwner(void)
    1286              : {
    1287        11797 :     TransactionState s = CurrentTransactionState;
    1288              : 
    1289              :     Assert(s->parent != NULL);
    1290              : 
    1291              :     /*
    1292              :      * Create a resource owner for the subtransaction.  We make it a child of
    1293              :      * the immediate parent's resource owner.
    1294              :      */
    1295        11797 :     s->curTransactionOwner =
    1296        11797 :         ResourceOwnerCreate(s->parent->curTransactionOwner,
    1297              :                             "SubTransaction");
    1298              : 
    1299        11797 :     CurTransactionResourceOwner = s->curTransactionOwner;
    1300        11797 :     CurrentResourceOwner = s->curTransactionOwner;
    1301        11797 : }
    1302              : 
    1303              : /* ----------------------------------------------------------------
    1304              :  *                      CommitTransaction stuff
    1305              :  * ----------------------------------------------------------------
    1306              :  */
    1307              : 
    1308              : /*
    1309              :  *  RecordTransactionCommit
    1310              :  *
    1311              :  * Returns latest XID among xact and its children, or InvalidTransactionId
    1312              :  * if the xact has no XID.  (We compute that here just because it's easier.)
    1313              :  *
    1314              :  * If you change this function, see RecordTransactionCommitPrepared also.
    1315              :  */
    1316              : static TransactionId
    1317       578009 : RecordTransactionCommit(void)
    1318              : {
    1319       578009 :     TransactionId xid = GetTopTransactionIdIfAny();
    1320       578009 :     bool        markXidCommitted = TransactionIdIsValid(xid);
    1321       578009 :     TransactionId latestXid = InvalidTransactionId;
    1322              :     int         nrels;
    1323              :     RelFileLocator *rels;
    1324              :     int         nchildren;
    1325              :     TransactionId *children;
    1326       578009 :     int         ndroppedstats = 0;
    1327       578009 :     xl_xact_stats_item *droppedstats = NULL;
    1328       578009 :     int         nmsgs = 0;
    1329       578009 :     SharedInvalidationMessage *invalMessages = NULL;
    1330       578009 :     bool        RelcacheInitFileInval = false;
    1331              :     bool        wrote_xlog;
    1332              : 
    1333              :     /*
    1334              :      * Log pending invalidations for logical decoding of in-progress
    1335              :      * transactions.  Normally for DDLs, we log this at each command end,
    1336              :      * however, for certain cases where we directly update the system table
    1337              :      * without a transaction block, the invalidations are not logged till this
    1338              :      * time.
    1339              :      */
    1340       578009 :     if (XLogLogicalInfoActive())
    1341        13950 :         LogLogicalInvalidations();
    1342              : 
    1343              :     /* Get data needed for commit record */
    1344       578009 :     nrels = smgrGetPendingDeletes(true, &rels);
    1345       578009 :     nchildren = xactGetCommittedChildren(&children);
    1346       578009 :     ndroppedstats = pgstat_get_transactional_drops(true, &droppedstats);
    1347       578009 :     if (XLogStandbyInfoActive())
    1348       261891 :         nmsgs = xactGetCommittedInvalidationMessages(&invalMessages,
    1349              :                                                      &RelcacheInitFileInval);
    1350       578009 :     wrote_xlog = (XactLastRecEnd != 0);
    1351              : 
    1352              :     /*
    1353              :      * If we haven't been assigned an XID yet, we neither can, nor do we want
    1354              :      * to write a COMMIT record.
    1355              :      */
    1356       578009 :     if (!markXidCommitted)
    1357              :     {
    1358              :         /*
    1359              :          * We expect that every RelationDropStorage is followed by a catalog
    1360              :          * update, and hence XID assignment, so we shouldn't get here with any
    1361              :          * pending deletes. Same is true for dropping stats.
    1362              :          *
    1363              :          * Use a real test not just an Assert to check this, since it's a bit
    1364              :          * fragile.
    1365              :          */
    1366       426588 :         if (nrels != 0 || ndroppedstats != 0)
    1367            0 :             elog(ERROR, "cannot commit a transaction that deleted files but has no xid");
    1368              : 
    1369              :         /* Can't have child XIDs either; AssignTransactionId enforces this */
    1370              :         Assert(nchildren == 0);
    1371              : 
    1372              :         /*
    1373              :          * Transactions without an assigned xid can contain invalidation
    1374              :          * messages.  While inplace updates do this, this is not known to be
    1375              :          * necessary; see comment at inplace CacheInvalidateHeapTuple().
    1376              :          * Extensions might still rely on this capability, and standbys may
    1377              :          * need to process those invals.  We can't emit a commit record
    1378              :          * without an xid, and we don't want to force assigning an xid,
    1379              :          * because that'd be problematic for e.g. vacuum.  Hence we emit a
    1380              :          * bespoke record for the invalidations. We don't want to use that in
    1381              :          * case a commit record is emitted, so they happen synchronously with
    1382              :          * commits (besides not wanting to emit more WAL records).
    1383              :          *
    1384              :          * XXX Every known use of this capability is a defect.  Since an XID
    1385              :          * isn't controlling visibility of the change that prompted invals,
    1386              :          * other sessions need the inval even if this transactions aborts.
    1387              :          *
    1388              :          * ON COMMIT DELETE ROWS does a nontransactional index_build(), which
    1389              :          * queues a relcache inval, including in transactions without an xid
    1390              :          * that had read the (empty) table.  Standbys don't need any ON COMMIT
    1391              :          * DELETE ROWS invals, but we've not done the work to withhold them.
    1392              :          */
    1393       426588 :         if (nmsgs != 0)
    1394              :         {
    1395        10378 :             LogStandbyInvalidations(nmsgs, invalMessages,
    1396              :                                     RelcacheInitFileInval);
    1397        10378 :             wrote_xlog = true;  /* not strictly necessary */
    1398              :         }
    1399              : 
    1400              :         /*
    1401              :          * If we didn't create XLOG entries, we're done here; otherwise we
    1402              :          * should trigger flushing those entries the same as a commit record
    1403              :          * would.  This will primarily happen for HOT pruning and the like; we
    1404              :          * want these to be flushed to disk in due time.
    1405              :          */
    1406       426588 :         if (!wrote_xlog)
    1407       387695 :             goto cleanup;
    1408              :     }
    1409              :     else
    1410              :     {
    1411              :         bool        replorigin;
    1412              : 
    1413              :         /*
    1414              :          * Are we using the replication origins feature?  Or, in other words,
    1415              :          * are we replaying remote actions?
    1416              :          */
    1417       152495 :         replorigin = (replorigin_xact_state.origin != InvalidReplOriginId &&
    1418         1074 :                       replorigin_xact_state.origin != DoNotReplicateId);
    1419              : 
    1420              :         /*
    1421              :          * Mark ourselves as within our "commit critical section".  This
    1422              :          * forces any concurrent checkpoint to wait until we've updated
    1423              :          * pg_xact.  Without this, it is possible for the checkpoint to set
    1424              :          * REDO after the XLOG record but fail to flush the pg_xact update to
    1425              :          * disk, leading to loss of the transaction commit if the system
    1426              :          * crashes a little later.
    1427              :          *
    1428              :          * Note: we could, but don't bother to, set this flag in
    1429              :          * RecordTransactionAbort.  That's because loss of a transaction abort
    1430              :          * is noncritical; the presumption would be that it aborted, anyway.
    1431              :          *
    1432              :          * It's safe to change the delayChkptFlags flag of our own backend
    1433              :          * without holding the ProcArrayLock, since we're the only one
    1434              :          * modifying it.  This makes checkpoint's determination of which xacts
    1435              :          * are delaying the checkpoint a bit fuzzy, but it doesn't matter.
    1436              :          *
    1437              :          * Note, it is important to get the commit timestamp after marking the
    1438              :          * transaction in the commit critical section. See
    1439              :          * RecordTransactionCommitPrepared.
    1440              :          */
    1441              :         Assert((MyProc->delayChkptFlags & DELAY_CHKPT_IN_COMMIT) == 0);
    1442       151421 :         START_CRIT_SECTION();
    1443       151421 :         MyProc->delayChkptFlags |= DELAY_CHKPT_IN_COMMIT;
    1444              : 
    1445              :         Assert(xactStopTimestamp == 0);
    1446              : 
    1447              :         /*
    1448              :          * Ensures the DELAY_CHKPT_IN_COMMIT flag write is globally visible
    1449              :          * before commit time is written.
    1450              :          */
    1451       151421 :         pg_write_barrier();
    1452              : 
    1453              :         /*
    1454              :          * Insert the commit XLOG record.
    1455              :          */
    1456       151421 :         XactLogCommitRecord(GetCurrentTransactionStopTimestamp(),
    1457              :                             nchildren, children, nrels, rels,
    1458              :                             ndroppedstats, droppedstats,
    1459              :                             nmsgs, invalMessages,
    1460              :                             RelcacheInitFileInval,
    1461              :                             MyXactFlags,
    1462              :                             InvalidTransactionId, NULL /* plain commit */ );
    1463              : 
    1464       151421 :         if (replorigin)
    1465              :             /* Move LSNs forward for this replication origin */
    1466         1074 :             replorigin_session_advance(replorigin_xact_state.origin_lsn,
    1467              :                                        XactLastRecEnd);
    1468              : 
    1469              :         /*
    1470              :          * Record commit timestamp.  The value comes from plain commit
    1471              :          * timestamp if there's no replication origin; otherwise, the
    1472              :          * timestamp was already set in replorigin_xact_state.origin_timestamp
    1473              :          * by replication.
    1474              :          *
    1475              :          * We don't need to WAL-log anything here, as the commit record
    1476              :          * written above already contains the data.
    1477              :          */
    1478              : 
    1479       151421 :         if (!replorigin || replorigin_xact_state.origin_timestamp == 0)
    1480       150464 :             replorigin_xact_state.origin_timestamp = GetCurrentTransactionStopTimestamp();
    1481              : 
    1482       151421 :         TransactionTreeSetCommitTsData(xid, nchildren, children,
    1483              :                                        replorigin_xact_state.origin_timestamp,
    1484       151421 :                                        replorigin_xact_state.origin);
    1485              :     }
    1486              : 
    1487              :     /*
    1488              :      * Check if we want to commit asynchronously.  We can allow the XLOG flush
    1489              :      * to happen asynchronously if synchronous_commit=off, or if the current
    1490              :      * transaction has not performed any WAL-logged operation or didn't assign
    1491              :      * an xid.  The transaction can end up not writing any WAL, even if it has
    1492              :      * an xid, if it only wrote to temporary and/or unlogged tables.  It can
    1493              :      * end up having written WAL without an xid if it did HOT pruning.  In
    1494              :      * case of a crash, the loss of such a transaction will be irrelevant;
    1495              :      * temp tables will be lost anyway, unlogged tables will be truncated and
    1496              :      * HOT pruning will be done again later. (Given the foregoing, you might
    1497              :      * think that it would be unnecessary to emit the XLOG record at all in
    1498              :      * this case, but we don't currently try to do that.  It would certainly
    1499              :      * cause problems at least in Hot Standby mode, where the
    1500              :      * KnownAssignedXids machinery requires tracking every XID assignment.  It
    1501              :      * might be OK to skip it only when wal_level < replica, but for now we
    1502              :      * don't.)
    1503              :      *
    1504              :      * However, if we're doing cleanup of any non-temp rels or committing any
    1505              :      * command that wanted to force sync commit, then we must flush XLOG
    1506              :      * immediately.  (We must not allow asynchronous commit if there are any
    1507              :      * non-temp tables to be deleted, because we might delete the files before
    1508              :      * the COMMIT record is flushed to disk.  We do allow asynchronous commit
    1509              :      * if all to-be-deleted tables are temporary though, since they are lost
    1510              :      * anyway if we crash.)
    1511              :      */
    1512       190314 :     if ((wrote_xlog && markXidCommitted &&
    1513       190314 :          synchronous_commit > SYNCHRONOUS_COMMIT_OFF) ||
    1514        46039 :         forceSyncCommit || nrels > 0)
    1515              :     {
    1516       144296 :         XLogFlush(XactLastRecEnd);
    1517              : 
    1518              :         /*
    1519              :          * Now we may update the CLOG, if we wrote a COMMIT record above
    1520              :          */
    1521       144296 :         if (markXidCommitted)
    1522       144296 :             TransactionIdCommitTree(xid, nchildren, children);
    1523              :     }
    1524              :     else
    1525              :     {
    1526              :         /*
    1527              :          * Asynchronous commit case:
    1528              :          *
    1529              :          * This enables possible committed transaction loss in the case of a
    1530              :          * postmaster crash because WAL buffers are left unwritten. Ideally we
    1531              :          * could issue the WAL write without the fsync, but some
    1532              :          * wal_sync_methods do not allow separate write/fsync.
    1533              :          *
    1534              :          * Report the latest async commit LSN, so that the WAL writer knows to
    1535              :          * flush this commit.
    1536              :          */
    1537        46018 :         XLogSetAsyncXactLSN(XactLastRecEnd);
    1538              : 
    1539              :         /*
    1540              :          * We must not immediately update the CLOG, since we didn't flush the
    1541              :          * XLOG. Instead, we store the LSN up to which the XLOG must be
    1542              :          * flushed before the CLOG may be updated.
    1543              :          */
    1544        46018 :         if (markXidCommitted)
    1545         7125 :             TransactionIdAsyncCommitTree(xid, nchildren, children, XactLastRecEnd);
    1546              :     }
    1547              : 
    1548              :     /*
    1549              :      * If we entered a commit critical section, leave it now, and let
    1550              :      * checkpoints proceed.
    1551              :      */
    1552       190314 :     if (markXidCommitted)
    1553              :     {
    1554       151421 :         MyProc->delayChkptFlags &= ~DELAY_CHKPT_IN_COMMIT;
    1555       151421 :         END_CRIT_SECTION();
    1556              :     }
    1557              : 
    1558              :     /* Compute latestXid while we have the child XIDs handy */
    1559       190314 :     latestXid = TransactionIdLatest(xid, nchildren, children);
    1560              : 
    1561              :     /*
    1562              :      * Wait for synchronous replication, if required. Similar to the decision
    1563              :      * above about using committing asynchronously we only want to wait if
    1564              :      * this backend assigned an xid and wrote WAL.  No need to wait if an xid
    1565              :      * was assigned due to temporary/unlogged tables or due to HOT pruning.
    1566              :      *
    1567              :      * Note that at this stage we have marked clog, but still show as running
    1568              :      * in the procarray and continue to hold locks.
    1569              :      */
    1570       190314 :     if (wrote_xlog && markXidCommitted)
    1571       146766 :         SyncRepWaitForLSN(XactLastRecEnd, true);
    1572              : 
    1573              :     /* remember end of last commit record */
    1574       190314 :     XactLastCommitEnd = XactLastRecEnd;
    1575              : 
    1576              :     /* Reset XactLastRecEnd until the next transaction writes something */
    1577       190314 :     XactLastRecEnd = 0;
    1578       578009 : cleanup:
    1579              :     /* Clean up local data */
    1580       578009 :     if (rels)
    1581        12132 :         pfree(rels);
    1582       578009 :     if (ndroppedstats)
    1583        14396 :         pfree(droppedstats);
    1584              : 
    1585       578009 :     return latestXid;
    1586              : }
    1587              : 
    1588              : 
    1589              : /*
    1590              :  *  AtCCI_LocalCache
    1591              :  */
    1592              : static void
    1593      1074258 : AtCCI_LocalCache(void)
    1594              : {
    1595              :     /*
    1596              :      * Make any pending relation map changes visible.  We must do this before
    1597              :      * processing local sinval messages, so that the map changes will get
    1598              :      * reflected into the relcache when relcache invals are processed.
    1599              :      */
    1600      1074258 :     AtCCI_RelationMap();
    1601              : 
    1602              :     /*
    1603              :      * Make catalog changes visible to me for the next command.
    1604              :      */
    1605      1074258 :     CommandEndInvalidationMessages();
    1606      1074254 : }
    1607              : 
    1608              : /*
    1609              :  *  AtCommit_Memory
    1610              :  */
    1611              : static void
    1612       580317 : AtCommit_Memory(void)
    1613              : {
    1614       580317 :     TransactionState s = CurrentTransactionState;
    1615              : 
    1616              :     /*
    1617              :      * Return to the memory context that was current before we started the
    1618              :      * transaction.  (In principle, this could not be any of the contexts we
    1619              :      * are about to delete.  If it somehow is, assertions in mcxt.c will
    1620              :      * complain.)
    1621              :      */
    1622       580317 :     MemoryContextSwitchTo(s->priorContext);
    1623              : 
    1624              :     /*
    1625              :      * Release all transaction-local memory.  TopTransactionContext survives
    1626              :      * but becomes empty; any sub-contexts go away.
    1627              :      */
    1628              :     Assert(TopTransactionContext != NULL);
    1629       580317 :     MemoryContextReset(TopTransactionContext);
    1630              : 
    1631              :     /*
    1632              :      * Clear these pointers as a pro-forma matter.  (Notionally, while
    1633              :      * TopTransactionContext still exists, it's currently not associated with
    1634              :      * this TransactionState struct.)
    1635              :      */
    1636       580317 :     CurTransactionContext = NULL;
    1637       580317 :     s->curTransactionContext = NULL;
    1638       580317 : }
    1639              : 
    1640              : /* ----------------------------------------------------------------
    1641              :  *                      CommitSubTransaction stuff
    1642              :  * ----------------------------------------------------------------
    1643              :  */
    1644              : 
    1645              : /*
    1646              :  * AtSubCommit_Memory
    1647              :  */
    1648              : static void
    1649         5855 : AtSubCommit_Memory(void)
    1650              : {
    1651         5855 :     TransactionState s = CurrentTransactionState;
    1652              : 
    1653              :     Assert(s->parent != NULL);
    1654              : 
    1655              :     /* Return to parent transaction level's memory context. */
    1656         5855 :     CurTransactionContext = s->parent->curTransactionContext;
    1657         5855 :     MemoryContextSwitchTo(CurTransactionContext);
    1658              : 
    1659              :     /*
    1660              :      * Ordinarily we cannot throw away the child's CurTransactionContext,
    1661              :      * since the data it contains will be needed at upper commit.  However, if
    1662              :      * there isn't actually anything in it, we can throw it away.  This avoids
    1663              :      * a small memory leak in the common case of "trivial" subxacts.
    1664              :      */
    1665         5855 :     if (MemoryContextIsEmpty(s->curTransactionContext))
    1666              :     {
    1667         5838 :         MemoryContextDelete(s->curTransactionContext);
    1668         5838 :         s->curTransactionContext = NULL;
    1669              :     }
    1670         5855 : }
    1671              : 
    1672              : /*
    1673              :  * AtSubCommit_childXids
    1674              :  *
    1675              :  * Pass my own XID and my child XIDs up to my parent as committed children.
    1676              :  */
    1677              : static void
    1678         3731 : AtSubCommit_childXids(void)
    1679              : {
    1680         3731 :     TransactionState s = CurrentTransactionState;
    1681              :     int         new_nChildXids;
    1682              : 
    1683              :     Assert(s->parent != NULL);
    1684              : 
    1685              :     /*
    1686              :      * The parent childXids array will need to hold my XID and all my
    1687              :      * childXids, in addition to the XIDs already there.
    1688              :      */
    1689         3731 :     new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
    1690              : 
    1691              :     /* Allocate or enlarge the parent array if necessary */
    1692         3731 :     if (s->parent->maxChildXids < new_nChildXids)
    1693              :     {
    1694              :         int         new_maxChildXids;
    1695              :         TransactionId *new_childXids;
    1696              : 
    1697              :         /*
    1698              :          * Make it 2x what's needed right now, to avoid having to enlarge it
    1699              :          * repeatedly. But we can't go above MaxAllocSize.  (The latter limit
    1700              :          * is what ensures that we don't need to worry about integer overflow
    1701              :          * here or in the calculation of new_nChildXids.)
    1702              :          */
    1703         1696 :         new_maxChildXids = Min(new_nChildXids * 2,
    1704              :                                (int) (MaxAllocSize / sizeof(TransactionId)));
    1705              : 
    1706         1696 :         if (new_maxChildXids < new_nChildXids)
    1707            0 :             ereport(ERROR,
    1708              :                     (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    1709              :                      errmsg("maximum number of committed subtransactions (%d) exceeded",
    1710              :                             (int) (MaxAllocSize / sizeof(TransactionId)))));
    1711              : 
    1712              :         /*
    1713              :          * We keep the child-XID arrays in TopTransactionContext; this avoids
    1714              :          * setting up child-transaction contexts for what might be just a few
    1715              :          * bytes of grandchild XIDs.
    1716              :          */
    1717         1696 :         if (s->parent->childXids == NULL)
    1718              :             new_childXids =
    1719         1651 :                 MemoryContextAlloc(TopTransactionContext,
    1720              :                                    new_maxChildXids * sizeof(TransactionId));
    1721              :         else
    1722           45 :             new_childXids = repalloc(s->parent->childXids,
    1723              :                                      new_maxChildXids * sizeof(TransactionId));
    1724              : 
    1725         1696 :         s->parent->childXids = new_childXids;
    1726         1696 :         s->parent->maxChildXids = new_maxChildXids;
    1727              :     }
    1728              : 
    1729              :     /*
    1730              :      * Copy all my XIDs to parent's array.
    1731              :      *
    1732              :      * Note: We rely on the fact that the XID of a child always follows that
    1733              :      * of its parent.  By copying the XID of this subtransaction before the
    1734              :      * XIDs of its children, we ensure that the array stays ordered. Likewise,
    1735              :      * all XIDs already in the array belong to subtransactions started and
    1736              :      * subcommitted before us, so their XIDs must precede ours.
    1737              :      */
    1738         3731 :     s->parent->childXids[s->parent->nChildXids] = XidFromFullTransactionId(s->fullTransactionId);
    1739              : 
    1740         3731 :     if (s->nChildXids > 0)
    1741         1017 :         memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
    1742         1017 :                s->childXids,
    1743         1017 :                s->nChildXids * sizeof(TransactionId));
    1744              : 
    1745         3731 :     s->parent->nChildXids = new_nChildXids;
    1746              : 
    1747              :     /* Release child's array to avoid leakage */
    1748         3731 :     if (s->childXids != NULL)
    1749         1017 :         pfree(s->childXids);
    1750              :     /* We must reset these to avoid double-free if fail later in commit */
    1751         3731 :     s->childXids = NULL;
    1752         3731 :     s->nChildXids = 0;
    1753         3731 :     s->maxChildXids = 0;
    1754         3731 : }
    1755              : 
    1756              : /* ----------------------------------------------------------------
    1757              :  *                      AbortTransaction stuff
    1758              :  * ----------------------------------------------------------------
    1759              :  */
    1760              : 
    1761              : /*
    1762              :  *  RecordTransactionAbort
    1763              :  *
    1764              :  * Returns latest XID among xact and its children, or InvalidTransactionId
    1765              :  * if the xact has no XID.  (We compute that here just because it's easier.)
    1766              :  */
    1767              : static TransactionId
    1768        40460 : RecordTransactionAbort(bool isSubXact)
    1769              : {
    1770        40460 :     TransactionId xid = GetCurrentTransactionIdIfAny();
    1771              :     TransactionId latestXid;
    1772              :     int         nrels;
    1773              :     RelFileLocator *rels;
    1774        40460 :     int         ndroppedstats = 0;
    1775        40460 :     xl_xact_stats_item *droppedstats = NULL;
    1776              :     int         nchildren;
    1777              :     TransactionId *children;
    1778              :     TimestampTz xact_time;
    1779              :     bool        replorigin;
    1780              : 
    1781              :     /*
    1782              :      * If we haven't been assigned an XID, nobody will care whether we aborted
    1783              :      * or not.  Hence, we're done in that case.  It does not matter if we have
    1784              :      * rels to delete (note that this routine is not responsible for actually
    1785              :      * deleting 'em).  We cannot have any child XIDs, either.
    1786              :      */
    1787        40460 :     if (!TransactionIdIsValid(xid))
    1788              :     {
    1789              :         /* Reset XactLastRecEnd until the next transaction writes something */
    1790        31831 :         if (!isSubXact)
    1791        26735 :             XactLastRecEnd = 0;
    1792        31831 :         return InvalidTransactionId;
    1793              :     }
    1794              : 
    1795              :     /*
    1796              :      * We have a valid XID, so we should write an ABORT record for it.
    1797              :      *
    1798              :      * We do not flush XLOG to disk here, since the default assumption after a
    1799              :      * crash would be that we aborted, anyway.  For the same reason, we don't
    1800              :      * need to worry about interlocking against checkpoint start.
    1801              :      */
    1802              : 
    1803              :     /*
    1804              :      * Check that we haven't aborted halfway through RecordTransactionCommit.
    1805              :      */
    1806         8629 :     if (TransactionIdDidCommit(xid))
    1807            0 :         elog(PANIC, "cannot abort transaction %u, it was already committed",
    1808              :              xid);
    1809              : 
    1810              :     /*
    1811              :      * Are we using the replication origins feature?  Or, in other words, are
    1812              :      * we replaying remote actions?
    1813              :      */
    1814         8653 :     replorigin = (replorigin_xact_state.origin != InvalidReplOriginId &&
    1815           24 :                   replorigin_xact_state.origin != DoNotReplicateId);
    1816              : 
    1817              :     /* Fetch the data we need for the abort record */
    1818         8629 :     nrels = smgrGetPendingDeletes(false, &rels);
    1819         8629 :     nchildren = xactGetCommittedChildren(&children);
    1820         8629 :     ndroppedstats = pgstat_get_transactional_drops(false, &droppedstats);
    1821              : 
    1822              :     /* XXX do we really need a critical section here? */
    1823         8629 :     START_CRIT_SECTION();
    1824              : 
    1825              :     /* Write the ABORT record */
    1826         8629 :     if (isSubXact)
    1827          846 :         xact_time = GetCurrentTimestamp();
    1828              :     else
    1829              :     {
    1830         7783 :         xact_time = GetCurrentTransactionStopTimestamp();
    1831              :     }
    1832              : 
    1833         8629 :     XactLogAbortRecord(xact_time,
    1834              :                        nchildren, children,
    1835              :                        nrels, rels,
    1836              :                        ndroppedstats, droppedstats,
    1837              :                        MyXactFlags, InvalidTransactionId,
    1838              :                        NULL);
    1839              : 
    1840         8629 :     if (replorigin)
    1841              :         /* Move LSNs forward for this replication origin */
    1842           24 :         replorigin_session_advance(replorigin_xact_state.origin_lsn,
    1843              :                                    XactLastRecEnd);
    1844              : 
    1845              :     /*
    1846              :      * Report the latest async abort LSN, so that the WAL writer knows to
    1847              :      * flush this abort. There's nothing to be gained by delaying this, since
    1848              :      * WALWriter may as well do this when it can. This is important with
    1849              :      * streaming replication because if we don't flush WAL regularly we will
    1850              :      * find that large aborts leave us with a long backlog for when commits
    1851              :      * occur after the abort, increasing our window of data loss should
    1852              :      * problems occur at that point.
    1853              :      */
    1854         8629 :     if (!isSubXact)
    1855         7783 :         XLogSetAsyncXactLSN(XactLastRecEnd);
    1856              : 
    1857              :     /*
    1858              :      * Mark the transaction aborted in clog.  This is not absolutely necessary
    1859              :      * but we may as well do it while we are here; also, in the subxact case
    1860              :      * it is helpful because XactLockTableWait makes use of it to avoid
    1861              :      * waiting for already-aborted subtransactions.  It is OK to do it without
    1862              :      * having flushed the ABORT record to disk, because in event of a crash
    1863              :      * we'd be assumed to have aborted anyway.
    1864              :      */
    1865         8629 :     TransactionIdAbortTree(xid, nchildren, children);
    1866              : 
    1867         8629 :     END_CRIT_SECTION();
    1868              : 
    1869              :     /* Compute latestXid while we have the child XIDs handy */
    1870         8629 :     latestXid = TransactionIdLatest(xid, nchildren, children);
    1871              : 
    1872              :     /*
    1873              :      * If we're aborting a subtransaction, we can immediately remove failed
    1874              :      * XIDs from PGPROC's cache of running child XIDs.  We do that here for
    1875              :      * subxacts, because we already have the child XID array at hand.  For
    1876              :      * main xacts, the equivalent happens just after this function returns.
    1877              :      */
    1878         8629 :     if (isSubXact)
    1879          846 :         XidCacheRemoveRunningXids(xid, nchildren, children, latestXid);
    1880              : 
    1881              :     /* Reset XactLastRecEnd until the next transaction writes something */
    1882         8629 :     if (!isSubXact)
    1883         7783 :         XactLastRecEnd = 0;
    1884              : 
    1885              :     /* And clean up local data */
    1886         8629 :     if (rels)
    1887         1359 :         pfree(rels);
    1888         8629 :     if (ndroppedstats)
    1889         1937 :         pfree(droppedstats);
    1890              : 
    1891         8629 :     return latestXid;
    1892              : }
    1893              : 
    1894              : /*
    1895              :  *  AtAbort_Memory
    1896              :  */
    1897              : static void
    1898        54313 : AtAbort_Memory(void)
    1899              : {
    1900              :     /*
    1901              :      * Switch into TransactionAbortContext, which should have some free space
    1902              :      * even if nothing else does.  We'll work in this context until we've
    1903              :      * finished cleaning up.
    1904              :      *
    1905              :      * It is barely possible to get here when we've not been able to create
    1906              :      * TransactionAbortContext yet; if so use TopMemoryContext.
    1907              :      */
    1908        54313 :     if (TransactionAbortContext != NULL)
    1909        54313 :         MemoryContextSwitchTo(TransactionAbortContext);
    1910              :     else
    1911            0 :         MemoryContextSwitchTo(TopMemoryContext);
    1912        54313 : }
    1913              : 
    1914              : /*
    1915              :  * AtSubAbort_Memory
    1916              :  */
    1917              : static void
    1918         5942 : AtSubAbort_Memory(void)
    1919              : {
    1920              :     Assert(TransactionAbortContext != NULL);
    1921              : 
    1922         5942 :     MemoryContextSwitchTo(TransactionAbortContext);
    1923         5942 : }
    1924              : 
    1925              : 
    1926              : /*
    1927              :  *  AtAbort_ResourceOwner
    1928              :  */
    1929              : static void
    1930        34526 : AtAbort_ResourceOwner(void)
    1931              : {
    1932              :     /*
    1933              :      * Make sure we have a valid ResourceOwner, if possible (else it will be
    1934              :      * NULL, which is OK)
    1935              :      */
    1936        34526 :     CurrentResourceOwner = TopTransactionResourceOwner;
    1937        34526 : }
    1938              : 
    1939              : /*
    1940              :  * AtSubAbort_ResourceOwner
    1941              :  */
    1942              : static void
    1943         5942 : AtSubAbort_ResourceOwner(void)
    1944              : {
    1945         5942 :     TransactionState s = CurrentTransactionState;
    1946              : 
    1947              :     /* Make sure we have a valid ResourceOwner */
    1948         5942 :     CurrentResourceOwner = s->curTransactionOwner;
    1949         5942 : }
    1950              : 
    1951              : 
    1952              : /*
    1953              :  * AtSubAbort_childXids
    1954              :  */
    1955              : static void
    1956          846 : AtSubAbort_childXids(void)
    1957              : {
    1958          846 :     TransactionState s = CurrentTransactionState;
    1959              : 
    1960              :     /*
    1961              :      * We keep the child-XID arrays in TopTransactionContext (see
    1962              :      * AtSubCommit_childXids).  This means we'd better free the array
    1963              :      * explicitly at abort to avoid leakage.
    1964              :      */
    1965          846 :     if (s->childXids != NULL)
    1966           26 :         pfree(s->childXids);
    1967          846 :     s->childXids = NULL;
    1968          846 :     s->nChildXids = 0;
    1969          846 :     s->maxChildXids = 0;
    1970              : 
    1971              :     /*
    1972              :      * We could prune the unreportedXids array here. But we don't bother. That
    1973              :      * would potentially reduce number of XLOG_XACT_ASSIGNMENT records but it
    1974              :      * would likely introduce more CPU time into the more common paths, so we
    1975              :      * choose not to do that.
    1976              :      */
    1977          846 : }
    1978              : 
    1979              : /* ----------------------------------------------------------------
    1980              :  *                      CleanupTransaction stuff
    1981              :  * ----------------------------------------------------------------
    1982              :  */
    1983              : 
    1984              : /*
    1985              :  *  AtCleanup_Memory
    1986              :  */
    1987              : static void
    1988        34526 : AtCleanup_Memory(void)
    1989              : {
    1990        34526 :     TransactionState s = CurrentTransactionState;
    1991              : 
    1992              :     /* Should be at top level */
    1993              :     Assert(s->parent == NULL);
    1994              : 
    1995              :     /*
    1996              :      * Return to the memory context that was current before we started the
    1997              :      * transaction.  (In principle, this could not be any of the contexts we
    1998              :      * are about to delete.  If it somehow is, assertions in mcxt.c will
    1999              :      * complain.)
    2000              :      */
    2001        34526 :     MemoryContextSwitchTo(s->priorContext);
    2002              : 
    2003              :     /*
    2004              :      * Clear the special abort context for next time.
    2005              :      */
    2006        34526 :     if (TransactionAbortContext != NULL)
    2007        34526 :         MemoryContextReset(TransactionAbortContext);
    2008              : 
    2009              :     /*
    2010              :      * Release all transaction-local memory, the same as in AtCommit_Memory,
    2011              :      * except we must cope with the possibility that we didn't get as far as
    2012              :      * creating TopTransactionContext.
    2013              :      */
    2014        34526 :     if (TopTransactionContext != NULL)
    2015        34526 :         MemoryContextReset(TopTransactionContext);
    2016              : 
    2017              :     /*
    2018              :      * Clear these pointers as a pro-forma matter.  (Notionally, while
    2019              :      * TopTransactionContext still exists, it's currently not associated with
    2020              :      * this TransactionState struct.)
    2021              :      */
    2022        34526 :     CurTransactionContext = NULL;
    2023        34526 :     s->curTransactionContext = NULL;
    2024        34526 : }
    2025              : 
    2026              : 
    2027              : /* ----------------------------------------------------------------
    2028              :  *                      CleanupSubTransaction stuff
    2029              :  * ----------------------------------------------------------------
    2030              :  */
    2031              : 
    2032              : /*
    2033              :  * AtSubCleanup_Memory
    2034              :  */
    2035              : static void
    2036         5942 : AtSubCleanup_Memory(void)
    2037              : {
    2038         5942 :     TransactionState s = CurrentTransactionState;
    2039              : 
    2040              :     Assert(s->parent != NULL);
    2041              : 
    2042              :     /*
    2043              :      * Return to the memory context that was current before we started the
    2044              :      * subtransaction.  (In principle, this could not be any of the contexts
    2045              :      * we are about to delete.  If it somehow is, assertions in mcxt.c will
    2046              :      * complain.)
    2047              :      */
    2048         5942 :     MemoryContextSwitchTo(s->priorContext);
    2049              : 
    2050              :     /* Update CurTransactionContext (might not be same as priorContext) */
    2051         5942 :     CurTransactionContext = s->parent->curTransactionContext;
    2052              : 
    2053              :     /*
    2054              :      * Clear the special abort context for next time.
    2055              :      */
    2056         5942 :     if (TransactionAbortContext != NULL)
    2057         5942 :         MemoryContextReset(TransactionAbortContext);
    2058              : 
    2059              :     /*
    2060              :      * Delete the subxact local memory contexts. Its CurTransactionContext can
    2061              :      * go too (note this also kills CurTransactionContexts from any children
    2062              :      * of the subxact).
    2063              :      */
    2064         5942 :     if (s->curTransactionContext)
    2065         5942 :         MemoryContextDelete(s->curTransactionContext);
    2066         5942 :     s->curTransactionContext = NULL;
    2067         5942 : }
    2068              : 
    2069              : /* ----------------------------------------------------------------
    2070              :  *                      interface routines
    2071              :  * ----------------------------------------------------------------
    2072              :  */
    2073              : 
    2074              : /*
    2075              :  *  StartTransaction
    2076              :  */
    2077              : static void
    2078       614843 : StartTransaction(void)
    2079              : {
    2080              :     TransactionState s;
    2081              :     VirtualTransactionId vxid;
    2082              : 
    2083              :     /*
    2084              :      * Let's just make sure the state stack is empty
    2085              :      */
    2086       614843 :     s = &TopTransactionStateData;
    2087       614843 :     CurrentTransactionState = s;
    2088              : 
    2089              :     Assert(!FullTransactionIdIsValid(XactTopFullTransactionId));
    2090              : 
    2091              :     /* check the current transaction state */
    2092              :     Assert(s->state == TRANS_DEFAULT);
    2093              : 
    2094              :     /*
    2095              :      * Set the current transaction state information appropriately during
    2096              :      * start processing.  Note that once the transaction status is switched
    2097              :      * this process cannot fail until the user ID and the security context
    2098              :      * flags are fetched below.
    2099              :      */
    2100       614843 :     s->state = TRANS_START;
    2101       614843 :     s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
    2102              : 
    2103              :     /* Determine if statements are logged in this transaction */
    2104       614843 :     xact_is_sampled = log_xact_sample_rate != 0 &&
    2105            0 :         (log_xact_sample_rate == 1 ||
    2106            0 :          pg_prng_double(&pg_global_prng_state) <= log_xact_sample_rate);
    2107              : 
    2108              :     /*
    2109              :      * initialize current transaction state fields
    2110              :      *
    2111              :      * note: prevXactReadOnly is not used at the outermost level
    2112              :      */
    2113       614843 :     s->nestingLevel = 1;
    2114       614843 :     s->gucNestLevel = 1;
    2115       614843 :     s->childXids = NULL;
    2116       614843 :     s->nChildXids = 0;
    2117       614843 :     s->maxChildXids = 0;
    2118              : 
    2119              :     /*
    2120              :      * Once the current user ID and the security context flags are fetched,
    2121              :      * both will be properly reset even if transaction startup fails.
    2122              :      */
    2123       614843 :     GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
    2124              : 
    2125              :     /* SecurityRestrictionContext should never be set outside a transaction */
    2126              :     Assert(s->prevSecContext == 0);
    2127              : 
    2128              :     /*
    2129              :      * Make sure we've reset xact state variables
    2130              :      *
    2131              :      * If recovery is still in progress, mark this transaction as read-only.
    2132              :      * We have lower level defences in XLogInsert and elsewhere to stop us
    2133              :      * from modifying data during recovery, but this gives the normal
    2134              :      * indication to the user that the transaction is read-only.
    2135              :      */
    2136       614843 :     if (RecoveryInProgress())
    2137              :     {
    2138         1857 :         s->startedInRecovery = true;
    2139         1857 :         XactReadOnly = true;
    2140              :     }
    2141              :     else
    2142              :     {
    2143       612986 :         s->startedInRecovery = false;
    2144       612986 :         XactReadOnly = DefaultXactReadOnly;
    2145              :     }
    2146       614843 :     XactDeferrable = DefaultXactDeferrable;
    2147       614843 :     XactIsoLevel = DefaultXactIsoLevel;
    2148       614843 :     forceSyncCommit = false;
    2149       614843 :     MyXactFlags = 0;
    2150              : 
    2151              :     /*
    2152              :      * reinitialize within-transaction counters
    2153              :      */
    2154       614843 :     s->subTransactionId = TopSubTransactionId;
    2155       614843 :     currentSubTransactionId = TopSubTransactionId;
    2156       614843 :     currentCommandId = FirstCommandId;
    2157       614843 :     currentCommandIdUsed = false;
    2158              : 
    2159              :     /*
    2160              :      * initialize reported xid accounting
    2161              :      */
    2162       614843 :     nUnreportedXids = 0;
    2163       614843 :     s->didLogXid = false;
    2164              : 
    2165              :     /*
    2166              :      * must initialize resource-management stuff first
    2167              :      */
    2168       614843 :     AtStart_Memory();
    2169       614843 :     AtStart_ResourceOwner();
    2170              : 
    2171              :     /*
    2172              :      * Assign a new LocalTransactionId, and combine it with the proc number to
    2173              :      * form a virtual transaction id.
    2174              :      */
    2175       614843 :     vxid.procNumber = MyProcNumber;
    2176       614843 :     vxid.localTransactionId = GetNextLocalTransactionId();
    2177              : 
    2178              :     /*
    2179              :      * Lock the virtual transaction id before we announce it in the proc array
    2180              :      */
    2181       614843 :     VirtualXactLockTableInsert(vxid);
    2182              : 
    2183              :     /*
    2184              :      * Advertise it in the proc array.  We assume assignment of
    2185              :      * localTransactionId is atomic, and the proc number should be set
    2186              :      * already.
    2187              :      */
    2188              :     Assert(MyProc->vxid.procNumber == vxid.procNumber);
    2189       614843 :     MyProc->vxid.lxid = vxid.localTransactionId;
    2190              : 
    2191              :     TRACE_POSTGRESQL_TRANSACTION_START(vxid.localTransactionId);
    2192              : 
    2193              :     /*
    2194              :      * set transaction_timestamp() (a/k/a now()).  Normally, we want this to
    2195              :      * be the same as the first command's statement_timestamp(), so don't do a
    2196              :      * fresh GetCurrentTimestamp() call (which'd be expensive anyway).  But
    2197              :      * for transactions started inside procedures (i.e., nonatomic SPI
    2198              :      * contexts), we do need to advance the timestamp.  Also, in a parallel
    2199              :      * worker, the timestamp should already have been provided by a call to
    2200              :      * SetParallelStartTimestamps().
    2201              :      */
    2202       614843 :     if (!IsParallelWorker())
    2203              :     {
    2204       608846 :         if (!SPI_inside_nonatomic_context())
    2205       606630 :             xactStartTimestamp = stmtStartTimestamp;
    2206              :         else
    2207         2216 :             xactStartTimestamp = GetCurrentTimestamp();
    2208              :     }
    2209              :     else
    2210              :         Assert(xactStartTimestamp != 0);
    2211       614843 :     pgstat_report_xact_timestamp(xactStartTimestamp);
    2212              :     /* Mark xactStopTimestamp as unset. */
    2213       614843 :     xactStopTimestamp = 0;
    2214              : 
    2215              :     /*
    2216              :      * initialize other subsystems for new transaction
    2217              :      */
    2218       614843 :     AtStart_GUC();
    2219       614843 :     AtStart_Cache();
    2220       614843 :     AfterTriggerBeginXact();
    2221              : 
    2222              :     /*
    2223              :      * done with start processing, set current transaction state to "in
    2224              :      * progress"
    2225              :      */
    2226       614843 :     s->state = TRANS_INPROGRESS;
    2227              : 
    2228              :     /* Schedule transaction timeout */
    2229       614843 :     if (TransactionTimeout > 0)
    2230            1 :         enable_timeout_after(TRANSACTION_TIMEOUT, TransactionTimeout);
    2231              : 
    2232       614843 :     ShowTransactionState("StartTransaction");
    2233       614843 : }
    2234              : 
    2235              : 
    2236              : /*
    2237              :  *  CommitTransaction
    2238              :  *
    2239              :  * NB: if you change this routine, better look at PrepareTransaction too!
    2240              :  */
    2241              : static void
    2242       580259 : CommitTransaction(void)
    2243              : {
    2244       580259 :     TransactionState s = CurrentTransactionState;
    2245              :     TransactionId latestXid;
    2246              :     bool        is_parallel_worker;
    2247              : 
    2248       580259 :     is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
    2249              : 
    2250              :     /* Enforce parallel mode restrictions during parallel worker commit. */
    2251       580259 :     if (is_parallel_worker)
    2252         1991 :         EnterParallelMode();
    2253              : 
    2254       580259 :     ShowTransactionState("CommitTransaction");
    2255              : 
    2256              :     /*
    2257              :      * check the current transaction state
    2258              :      */
    2259       580259 :     if (s->state != TRANS_INPROGRESS)
    2260            0 :         elog(WARNING, "CommitTransaction while in %s state",
    2261              :              TransStateAsString(s->state));
    2262              :     Assert(s->parent == NULL);
    2263              : 
    2264              :     /*
    2265              :      * Do pre-commit processing that involves calling user-defined code, such
    2266              :      * as triggers.  SECURITY_RESTRICTED_OPERATION contexts must not queue an
    2267              :      * action that would run here, because that would bypass the sandbox.
    2268              :      * Since closing cursors could queue trigger actions, triggers could open
    2269              :      * cursors, etc, we have to keep looping until there's nothing left to do.
    2270              :      */
    2271              :     for (;;)
    2272              :     {
    2273              :         /*
    2274              :          * Fire all currently pending deferred triggers.
    2275              :          */
    2276       585868 :         AfterTriggerFireDeferred();
    2277              : 
    2278              :         /*
    2279              :          * Close open portals (converting holdable ones into static portals).
    2280              :          * If there weren't any, we are done ... otherwise loop back to check
    2281              :          * if they queued deferred triggers.  Lather, rinse, repeat.
    2282              :          */
    2283       585768 :         if (!PreCommit_Portals(false))
    2284       580159 :             break;
    2285              :     }
    2286              : 
    2287              :     /*
    2288              :      * The remaining actions cannot call any user-defined code, so it's safe
    2289              :      * to start shutting down within-transaction services.  But note that most
    2290              :      * of this stuff could still throw an error, which would switch us into
    2291              :      * the transaction-abort path.
    2292              :      */
    2293              : 
    2294       580159 :     CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_PRE_COMMIT
    2295              :                       : XACT_EVENT_PRE_COMMIT);
    2296              : 
    2297              :     /*
    2298              :      * If this xact has started any unfinished parallel operation, clean up
    2299              :      * its workers, warning about leaked resources.  (But we don't actually
    2300              :      * reset parallelModeLevel till entering TRANS_COMMIT, a bit below.  This
    2301              :      * keeps parallel mode restrictions active as long as possible in a
    2302              :      * parallel worker.)
    2303              :      */
    2304       580159 :     AtEOXact_Parallel(true);
    2305       580159 :     if (is_parallel_worker)
    2306              :     {
    2307         1991 :         if (s->parallelModeLevel != 1)
    2308            0 :             elog(WARNING, "parallelModeLevel is %d not 1 at end of parallel worker transaction",
    2309              :                  s->parallelModeLevel);
    2310              :     }
    2311              :     else
    2312              :     {
    2313       578168 :         if (s->parallelModeLevel != 0)
    2314            0 :             elog(WARNING, "parallelModeLevel is %d not 0 at end of transaction",
    2315              :                  s->parallelModeLevel);
    2316              :     }
    2317              : 
    2318              :     /* Shut down the deferred-trigger manager */
    2319       580159 :     AfterTriggerEndXact(true);
    2320              : 
    2321              :     /*
    2322              :      * Let ON COMMIT management do its thing (must happen after closing
    2323              :      * cursors, to avoid dangling-reference problems)
    2324              :      */
    2325       580159 :     PreCommit_on_commit_actions();
    2326              : 
    2327              :     /*
    2328              :      * Synchronize files that are created and not WAL-logged during this
    2329              :      * transaction. This must happen before AtEOXact_RelationMap(), so that we
    2330              :      * don't see committed-but-broken files after a crash.
    2331              :      */
    2332       580155 :     smgrDoPendingSyncs(true, is_parallel_worker);
    2333              : 
    2334              :     /* close large objects before lower-level cleanup */
    2335       580155 :     AtEOXact_LargeObject(true);
    2336              : 
    2337              :     /*
    2338              :      * Insert notifications sent by NOTIFY commands into the queue.  This
    2339              :      * should be late in the pre-commit sequence to minimize time spent
    2340              :      * holding the notify-insertion lock.  However, this could result in
    2341              :      * creating a snapshot, so we must do it before serializable cleanup.
    2342              :      */
    2343       580155 :     PreCommit_Notify();
    2344              : 
    2345              :     /*
    2346              :      * Mark serializable transaction as complete for predicate locking
    2347              :      * purposes.  This should be done as late as we can put it and still allow
    2348              :      * errors to be raised for failure patterns found at commit.  This is not
    2349              :      * appropriate in a parallel worker however, because we aren't committing
    2350              :      * the leader's transaction and its serializable state will live on.
    2351              :      */
    2352       580155 :     if (!is_parallel_worker)
    2353       578164 :         PreCommit_CheckForSerializationFailure();
    2354              : 
    2355              :     /* Prevent cancel/die interrupt while cleaning up */
    2356       580000 :     HOLD_INTERRUPTS();
    2357              : 
    2358              :     /* Commit updates to the relation map --- do this as late as possible */
    2359       580000 :     AtEOXact_RelationMap(true, is_parallel_worker);
    2360              : 
    2361              :     /*
    2362              :      * set the current transaction state information appropriately during
    2363              :      * commit processing
    2364              :      */
    2365       580000 :     s->state = TRANS_COMMIT;
    2366       580000 :     s->parallelModeLevel = 0;
    2367       580000 :     s->parallelChildXact = false;    /* should be false already */
    2368              : 
    2369              :     /* Disable transaction timeout */
    2370       580000 :     if (TransactionTimeout > 0)
    2371            1 :         disable_timeout(TRANSACTION_TIMEOUT, false);
    2372              : 
    2373       580000 :     if (!is_parallel_worker)
    2374              :     {
    2375              :         /*
    2376              :          * We need to mark our XIDs as committed in pg_xact.  This is where we
    2377              :          * durably commit.
    2378              :          */
    2379       578009 :         latestXid = RecordTransactionCommit();
    2380              :     }
    2381              :     else
    2382              :     {
    2383              :         /*
    2384              :          * We must not mark our XID committed; the parallel leader is
    2385              :          * responsible for that.
    2386              :          */
    2387         1991 :         latestXid = InvalidTransactionId;
    2388              : 
    2389              :         /*
    2390              :          * Make sure the leader will know about any WAL we wrote before it
    2391              :          * commits.
    2392              :          */
    2393         1991 :         ParallelWorkerReportLastRecEnd(XactLastRecEnd);
    2394              :     }
    2395              : 
    2396              :     TRACE_POSTGRESQL_TRANSACTION_COMMIT(MyProc->vxid.lxid);
    2397              : 
    2398              :     /*
    2399              :      * Let others know about no transaction in progress by me. Note that this
    2400              :      * must be done _before_ releasing locks we hold and _after_
    2401              :      * RecordTransactionCommit.
    2402              :      */
    2403       580000 :     ProcArrayEndTransaction(MyProc, latestXid);
    2404              : 
    2405              :     /*
    2406              :      * This is all post-commit cleanup.  Note that if an error is raised here,
    2407              :      * it's too late to abort the transaction.  This should be just
    2408              :      * noncritical resource releasing.
    2409              :      *
    2410              :      * The ordering of operations is not entirely random.  The idea is:
    2411              :      * release resources visible to other backends (eg, files, buffer pins);
    2412              :      * then release locks; then release backend-local resources. We want to
    2413              :      * release locks at the point where any backend waiting for us will see
    2414              :      * our transaction as being fully cleaned up.
    2415              :      *
    2416              :      * Resources that can be associated with individual queries are handled by
    2417              :      * the ResourceOwner mechanism.  The other calls here are for backend-wide
    2418              :      * state.
    2419              :      */
    2420              : 
    2421       580000 :     CallXactCallbacks(is_parallel_worker ? XACT_EVENT_PARALLEL_COMMIT
    2422              :                       : XACT_EVENT_COMMIT);
    2423              : 
    2424       580000 :     CurrentResourceOwner = NULL;
    2425       580000 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2426              :                          RESOURCE_RELEASE_BEFORE_LOCKS,
    2427              :                          true, true);
    2428              : 
    2429       580000 :     AtEOXact_Aio(true);
    2430              : 
    2431              :     /* Check we've released all buffer pins */
    2432       580000 :     AtEOXact_Buffers(true);
    2433              : 
    2434              :     /* Clean up the relation cache */
    2435       580000 :     AtEOXact_RelationCache(true);
    2436              : 
    2437              :     /* Clean up the type cache */
    2438       580000 :     AtEOXact_TypeCache();
    2439              : 
    2440              :     /*
    2441              :      * Make catalog changes visible to all backends.  This has to happen after
    2442              :      * relcache references are dropped (see comments for
    2443              :      * AtEOXact_RelationCache), but before locks are released (if anyone is
    2444              :      * waiting for lock on a relation we've modified, we want them to know
    2445              :      * about the catalog change before they start using the relation).
    2446              :      */
    2447       580000 :     AtEOXact_Inval(true);
    2448              : 
    2449       580000 :     AtEOXact_MultiXact();
    2450              : 
    2451       580000 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2452              :                          RESOURCE_RELEASE_LOCKS,
    2453              :                          true, true);
    2454       580000 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2455              :                          RESOURCE_RELEASE_AFTER_LOCKS,
    2456              :                          true, true);
    2457              : 
    2458              :     /*
    2459              :      * Likewise, dropping of files deleted during the transaction is best done
    2460              :      * after releasing relcache and buffer pins.  (This is not strictly
    2461              :      * necessary during commit, since such pins should have been released
    2462              :      * already, but this ordering is definitely critical during abort.)  Since
    2463              :      * this may take many seconds, also delay until after releasing locks.
    2464              :      * Other backends will observe the attendant catalog changes and not
    2465              :      * attempt to access affected files.
    2466              :      */
    2467       580000 :     smgrDoPendingDeletes(true);
    2468              : 
    2469              :     /*
    2470              :      * Send out notification signals to other backends (and do other
    2471              :      * post-commit NOTIFY cleanup).  This must not happen until after our
    2472              :      * transaction is fully done from the viewpoint of other backends.
    2473              :      */
    2474       580000 :     AtCommit_Notify();
    2475              : 
    2476              :     /*
    2477              :      * Everything after this should be purely internal-to-this-backend
    2478              :      * cleanup.
    2479              :      */
    2480       580000 :     AtEOXact_GUC(true, 1);
    2481       580000 :     AtEOXact_SPI(true);
    2482       580000 :     AtEOXact_Enum();
    2483       580000 :     AtEOXact_on_commit_actions(true);
    2484       580000 :     AtEOXact_Namespace(true, is_parallel_worker);
    2485       580000 :     AtEOXact_SMgr();
    2486       580000 :     AtEOXact_Files(true);
    2487       580000 :     AtEOXact_ComboCid();
    2488       580000 :     AtEOXact_HashTables(true);
    2489       580000 :     AtEOXact_PgStat(true, is_parallel_worker);
    2490       580000 :     AtEOXact_Snapshot(true, false);
    2491       580000 :     AtEOXact_ApplyLauncher(true);
    2492       580000 :     AtEOXact_LogicalRepWorkers(true);
    2493       580000 :     AtEOXact_LogicalCtl();
    2494       580000 :     pgstat_report_xact_timestamp(0);
    2495              : 
    2496       580000 :     ResourceOwnerDelete(TopTransactionResourceOwner);
    2497       580000 :     s->curTransactionOwner = NULL;
    2498       580000 :     CurTransactionResourceOwner = NULL;
    2499       580000 :     TopTransactionResourceOwner = NULL;
    2500              : 
    2501       580000 :     AtCommit_Memory();
    2502              : 
    2503       580000 :     s->fullTransactionId = InvalidFullTransactionId;
    2504       580000 :     s->subTransactionId = InvalidSubTransactionId;
    2505       580000 :     s->nestingLevel = 0;
    2506       580000 :     s->gucNestLevel = 0;
    2507       580000 :     s->childXids = NULL;
    2508       580000 :     s->nChildXids = 0;
    2509       580000 :     s->maxChildXids = 0;
    2510              : 
    2511       580000 :     XactTopFullTransactionId = InvalidFullTransactionId;
    2512       580000 :     nParallelCurrentXids = 0;
    2513              : 
    2514              :     /*
    2515              :      * done with commit processing, set current transaction state back to
    2516              :      * default
    2517              :      */
    2518       580000 :     s->state = TRANS_DEFAULT;
    2519              : 
    2520       580000 :     RESUME_INTERRUPTS();
    2521       580000 : }
    2522              : 
    2523              : 
    2524              : /*
    2525              :  *  PrepareTransaction
    2526              :  *
    2527              :  * NB: if you change this routine, better look at CommitTransaction too!
    2528              :  */
    2529              : static void
    2530          386 : PrepareTransaction(void)
    2531              : {
    2532          386 :     TransactionState s = CurrentTransactionState;
    2533          386 :     FullTransactionId fxid = GetCurrentFullTransactionId();
    2534              :     GlobalTransaction gxact;
    2535              :     TimestampTz prepared_at;
    2536              : 
    2537              :     Assert(!IsInParallelMode());
    2538              : 
    2539          386 :     ShowTransactionState("PrepareTransaction");
    2540              : 
    2541              :     /*
    2542              :      * check the current transaction state
    2543              :      */
    2544          386 :     if (s->state != TRANS_INPROGRESS)
    2545            0 :         elog(WARNING, "PrepareTransaction while in %s state",
    2546              :              TransStateAsString(s->state));
    2547              :     Assert(s->parent == NULL);
    2548              : 
    2549              :     /*
    2550              :      * Do pre-commit processing that involves calling user-defined code, such
    2551              :      * as triggers.  Since closing cursors could queue trigger actions,
    2552              :      * triggers could open cursors, etc, we have to keep looping until there's
    2553              :      * nothing left to do.
    2554              :      */
    2555              :     for (;;)
    2556              :     {
    2557              :         /*
    2558              :          * Fire all currently pending deferred triggers.
    2559              :          */
    2560          388 :         AfterTriggerFireDeferred();
    2561              : 
    2562              :         /*
    2563              :          * Close open portals (converting holdable ones into static portals).
    2564              :          * If there weren't any, we are done ... otherwise loop back to check
    2565              :          * if they queued deferred triggers.  Lather, rinse, repeat.
    2566              :          */
    2567          388 :         if (!PreCommit_Portals(true))
    2568          386 :             break;
    2569              :     }
    2570              : 
    2571          386 :     CallXactCallbacks(XACT_EVENT_PRE_PREPARE);
    2572              : 
    2573              :     /*
    2574              :      * The remaining actions cannot call any user-defined code, so it's safe
    2575              :      * to start shutting down within-transaction services.  But note that most
    2576              :      * of this stuff could still throw an error, which would switch us into
    2577              :      * the transaction-abort path.
    2578              :      */
    2579              : 
    2580              :     /* Shut down the deferred-trigger manager */
    2581          385 :     AfterTriggerEndXact(true);
    2582              : 
    2583              :     /*
    2584              :      * Let ON COMMIT management do its thing (must happen after closing
    2585              :      * cursors, to avoid dangling-reference problems)
    2586              :      */
    2587          385 :     PreCommit_on_commit_actions();
    2588              : 
    2589              :     /*
    2590              :      * Synchronize files that are created and not WAL-logged during this
    2591              :      * transaction. This must happen before EndPrepare(), so that we don't see
    2592              :      * committed-but-broken files after a crash and COMMIT PREPARED.
    2593              :      */
    2594          385 :     smgrDoPendingSyncs(true, false);
    2595              : 
    2596              :     /* close large objects before lower-level cleanup */
    2597          385 :     AtEOXact_LargeObject(true);
    2598              : 
    2599              :     /* NOTIFY requires no work at this point */
    2600              : 
    2601              :     /*
    2602              :      * Mark serializable transaction as complete for predicate locking
    2603              :      * purposes.  This should be done as late as we can put it and still allow
    2604              :      * errors to be raised for failure patterns found at commit.
    2605              :      */
    2606          385 :     PreCommit_CheckForSerializationFailure();
    2607              : 
    2608              :     /*
    2609              :      * Don't allow PREPARE TRANSACTION if we've accessed a temporary table in
    2610              :      * this transaction.  Having the prepared xact hold locks on another
    2611              :      * backend's temp table seems a bad idea --- for instance it would prevent
    2612              :      * the backend from exiting.  There are other problems too, such as how to
    2613              :      * clean up the source backend's local buffers and ON COMMIT state if the
    2614              :      * prepared xact includes a DROP of a temp table.
    2615              :      *
    2616              :      * Other objects types, like functions, operators or extensions, share the
    2617              :      * same restriction as they should not be created, locked or dropped as
    2618              :      * this can mess up with this session or even a follow-up session trying
    2619              :      * to use the same temporary namespace.
    2620              :      *
    2621              :      * We must check this after executing any ON COMMIT actions, because they
    2622              :      * might still access a temp relation.
    2623              :      *
    2624              :      * XXX In principle this could be relaxed to allow some useful special
    2625              :      * cases, such as a temp table created and dropped all within the
    2626              :      * transaction.  That seems to require much more bookkeeping though.
    2627              :      */
    2628          385 :     if ((MyXactFlags & XACT_FLAGS_ACCESSEDTEMPNAMESPACE))
    2629           45 :         ereport(ERROR,
    2630              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2631              :                  errmsg("cannot PREPARE a transaction that has operated on temporary objects")));
    2632              : 
    2633              :     /*
    2634              :      * Likewise, don't allow PREPARE after pg_export_snapshot.  This could be
    2635              :      * supported if we added cleanup logic to twophase.c, but for now it
    2636              :      * doesn't seem worth the trouble.
    2637              :      */
    2638          340 :     if (XactHasExportedSnapshots())
    2639            0 :         ereport(ERROR,
    2640              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    2641              :                  errmsg("cannot PREPARE a transaction that has exported snapshots")));
    2642              : 
    2643              :     /* Prevent cancel/die interrupt while cleaning up */
    2644          340 :     HOLD_INTERRUPTS();
    2645              : 
    2646              :     /*
    2647              :      * set the current transaction state information appropriately during
    2648              :      * prepare processing
    2649              :      */
    2650          340 :     s->state = TRANS_PREPARE;
    2651              : 
    2652              :     /* Disable transaction timeout */
    2653          340 :     if (TransactionTimeout > 0)
    2654            0 :         disable_timeout(TRANSACTION_TIMEOUT, false);
    2655              : 
    2656          340 :     prepared_at = GetCurrentTimestamp();
    2657              : 
    2658              :     /*
    2659              :      * Reserve the GID for this transaction. This could fail if the requested
    2660              :      * GID is invalid or already in use.
    2661              :      */
    2662          340 :     gxact = MarkAsPreparing(fxid, prepareGID, prepared_at,
    2663              :                             GetUserId(), MyDatabaseId);
    2664          319 :     prepareGID = NULL;
    2665              : 
    2666              :     /*
    2667              :      * Collect data for the 2PC state file.  Note that in general, no actual
    2668              :      * state change should happen in the called modules during this step,
    2669              :      * since it's still possible to fail before commit, and in that case we
    2670              :      * want transaction abort to be able to clean up.  (In particular, the
    2671              :      * AtPrepare routines may error out if they find cases they cannot
    2672              :      * handle.)  State cleanup should happen in the PostPrepare routines
    2673              :      * below.  However, some modules can go ahead and clear state here because
    2674              :      * they wouldn't do anything with it during abort anyway.
    2675              :      *
    2676              :      * Note: because the 2PC state file records will be replayed in the same
    2677              :      * order they are made, the order of these calls has to match the order in
    2678              :      * which we want things to happen during COMMIT PREPARED or ROLLBACK
    2679              :      * PREPARED; in particular, pay attention to whether things should happen
    2680              :      * before or after releasing the transaction's locks.
    2681              :      */
    2682          319 :     StartPrepare(gxact);
    2683              : 
    2684          319 :     AtPrepare_Notify();
    2685          319 :     AtPrepare_Locks();
    2686          317 :     AtPrepare_PredicateLocks();
    2687          317 :     AtPrepare_PgStat();
    2688          317 :     AtPrepare_MultiXact();
    2689          317 :     AtPrepare_RelationMap();
    2690              : 
    2691              :     /*
    2692              :      * Here is where we really truly prepare.
    2693              :      *
    2694              :      * We have to record transaction prepares even if we didn't make any
    2695              :      * updates, because the transaction manager might get confused if we lose
    2696              :      * a global transaction.
    2697              :      */
    2698          317 :     EndPrepare(gxact);
    2699              : 
    2700              :     /*
    2701              :      * Now we clean up backend-internal state and release internal resources.
    2702              :      */
    2703              : 
    2704              :     /* Reset XactLastRecEnd until the next transaction writes something */
    2705          317 :     XactLastRecEnd = 0;
    2706              : 
    2707              :     /*
    2708              :      * Transfer our locks to a dummy PGPROC.  This has to be done before
    2709              :      * ProcArrayClearTransaction().  Otherwise, a GetLockConflicts() would
    2710              :      * conclude "xact already committed or aborted" for our locks.
    2711              :      */
    2712          317 :     PostPrepare_Locks(fxid);
    2713              : 
    2714              :     /*
    2715              :      * Let others know about no transaction in progress by me.  This has to be
    2716              :      * done *after* the prepared transaction has been marked valid, else
    2717              :      * someone may think it is unlocked and recyclable.
    2718              :      */
    2719          317 :     ProcArrayClearTransaction(MyProc);
    2720              : 
    2721              :     /*
    2722              :      * In normal commit-processing, this is all non-critical post-transaction
    2723              :      * cleanup.  When the transaction is prepared, however, it's important
    2724              :      * that the locks and other per-backend resources are transferred to the
    2725              :      * prepared transaction's PGPROC entry.  Note that if an error is raised
    2726              :      * here, it's too late to abort the transaction. XXX: This probably should
    2727              :      * be in a critical section, to force a PANIC if any of this fails, but
    2728              :      * that cure could be worse than the disease.
    2729              :      */
    2730              : 
    2731          317 :     CallXactCallbacks(XACT_EVENT_PREPARE);
    2732              : 
    2733          317 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2734              :                          RESOURCE_RELEASE_BEFORE_LOCKS,
    2735              :                          true, true);
    2736              : 
    2737          317 :     AtEOXact_Aio(true);
    2738              : 
    2739              :     /* Check we've released all buffer pins */
    2740          317 :     AtEOXact_Buffers(true);
    2741              : 
    2742              :     /* Clean up the relation cache */
    2743          317 :     AtEOXact_RelationCache(true);
    2744              : 
    2745              :     /* Clean up the type cache */
    2746          317 :     AtEOXact_TypeCache();
    2747              : 
    2748              :     /* notify doesn't need a postprepare call */
    2749              : 
    2750          317 :     PostPrepare_PgStat();
    2751              : 
    2752          317 :     PostPrepare_Inval();
    2753              : 
    2754          317 :     PostPrepare_smgr();
    2755              : 
    2756          317 :     PostPrepare_MultiXact(fxid);
    2757              : 
    2758          317 :     PostPrepare_PredicateLocks(fxid);
    2759              : 
    2760          317 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2761              :                          RESOURCE_RELEASE_LOCKS,
    2762              :                          true, true);
    2763          317 :     ResourceOwnerRelease(TopTransactionResourceOwner,
    2764              :                          RESOURCE_RELEASE_AFTER_LOCKS,
    2765              :                          true, true);
    2766              : 
    2767              :     /*
    2768              :      * Allow another backend to finish the transaction.  After
    2769              :      * PostPrepare_Twophase(), the transaction is completely detached from our
    2770              :      * backend.  The rest is just non-critical cleanup of backend-local state.
    2771              :      */
    2772          317 :     PostPrepare_Twophase();
    2773              : 
    2774              :     /* PREPARE acts the same as COMMIT as far as GUC is concerned */
    2775          317 :     AtEOXact_GUC(true, 1);
    2776          317 :     AtEOXact_SPI(true);
    2777          317 :     AtEOXact_Enum();
    2778          317 :     AtEOXact_on_commit_actions(true);
    2779          317 :     AtEOXact_Namespace(true, false);
    2780          317 :     AtEOXact_SMgr();
    2781          317 :     AtEOXact_Files(true);
    2782          317 :     AtEOXact_ComboCid();
    2783          317 :     AtEOXact_HashTables(true);
    2784              :     /* don't call AtEOXact_PgStat here; we fixed pgstat state above */
    2785          317 :     AtEOXact_Snapshot(true, true);
    2786              :     /* we treat PREPARE as ROLLBACK so far as waking workers goes */
    2787          317 :     AtEOXact_ApplyLauncher(false);
    2788          317 :     AtEOXact_LogicalRepWorkers(false);
    2789          317 :     AtEOXact_LogicalCtl();
    2790          317 :     pgstat_report_xact_timestamp(0);
    2791              : 
    2792          317 :     CurrentResourceOwner = NULL;
    2793          317 :     ResourceOwnerDelete(TopTransactionResourceOwner);
    2794          317 :     s->curTransactionOwner = NULL;
    2795          317 :     CurTransactionResourceOwner = NULL;
    2796          317 :     TopTransactionResourceOwner = NULL;
    2797              : 
    2798          317 :     AtCommit_Memory();
    2799              : 
    2800          317 :     s->fullTransactionId = InvalidFullTransactionId;
    2801          317 :     s->subTransactionId = InvalidSubTransactionId;
    2802          317 :     s->nestingLevel = 0;
    2803          317 :     s->gucNestLevel = 0;
    2804          317 :     s->childXids = NULL;
    2805          317 :     s->nChildXids = 0;
    2806          317 :     s->maxChildXids = 0;
    2807              : 
    2808          317 :     XactTopFullTransactionId = InvalidFullTransactionId;
    2809          317 :     nParallelCurrentXids = 0;
    2810              : 
    2811              :     /*
    2812              :      * done with 1st phase commit processing, set current transaction state
    2813              :      * back to default
    2814              :      */
    2815          317 :     s->state = TRANS_DEFAULT;
    2816              : 
    2817          317 :     RESUME_INTERRUPTS();
    2818          317 : }
    2819              : 
    2820              : 
    2821              : /*
    2822              :  *  AbortTransaction
    2823              :  */
    2824              : static void
    2825        34526 : AbortTransaction(void)
    2826              : {
    2827        34526 :     TransactionState s = CurrentTransactionState;
    2828              :     TransactionId latestXid;
    2829              :     bool        is_parallel_worker;
    2830              : 
    2831              :     /* Prevent cancel/die interrupt while cleaning up */
    2832        34526 :     HOLD_INTERRUPTS();
    2833              : 
    2834              :     /* Disable transaction timeout */
    2835        34526 :     if (TransactionTimeout > 0)
    2836            1 :         disable_timeout(TRANSACTION_TIMEOUT, false);
    2837              : 
    2838              :     /* Make sure we have a valid memory context and resource owner */
    2839        34526 :     AtAbort_Memory();
    2840        34526 :     AtAbort_ResourceOwner();
    2841              : 
    2842              :     /*
    2843              :      * Release any LW locks we might be holding as quickly as possible.
    2844              :      * (Regular locks, however, must be held till we finish aborting.)
    2845              :      * Releasing LW locks is critical since we might try to grab them again
    2846              :      * while cleaning up!
    2847              :      */
    2848        34526 :     LWLockReleaseAll();
    2849              : 
    2850              :     /*
    2851              :      * Cleanup waiting for LSN if any.
    2852              :      */
    2853        34526 :     WaitLSNCleanup();
    2854              : 
    2855              :     /* Clear wait information and command progress indicator */
    2856        34526 :     pgstat_report_wait_end();
    2857        34526 :     pgstat_progress_end_command();
    2858              : 
    2859        34526 :     pgaio_error_cleanup();
    2860              : 
    2861              :     /* Clean up buffer content locks, too */
    2862        34526 :     UnlockBuffers();
    2863              : 
    2864              :     /* Reset WAL record construction state */
    2865        34526 :     XLogResetInsertion();
    2866              : 
    2867              :     /* Cancel condition variable sleep */
    2868        34526 :     ConditionVariableCancelSleep();
    2869              : 
    2870              :     /*
    2871              :      * Also clean up any open wait for lock, since the lock manager will choke
    2872              :      * if we try to wait for another lock before doing this.
    2873              :      */
    2874        34526 :     LockErrorCleanup();
    2875              : 
    2876              :     /*
    2877              :      * If any timeout events are still active, make sure the timeout interrupt
    2878              :      * is scheduled.  This covers possible loss of a timeout interrupt due to
    2879              :      * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
    2880              :      * We delay this till after LockErrorCleanup so that we don't uselessly
    2881              :      * reschedule lock or deadlock check timeouts.
    2882              :      */
    2883        34526 :     reschedule_timeouts();
    2884              : 
    2885              :     /*
    2886              :      * Re-enable signals, in case we got here by longjmp'ing out of a signal
    2887              :      * handler.  We do this fairly early in the sequence so that the timeout
    2888              :      * infrastructure will be functional if needed while aborting.
    2889              :      */
    2890        34526 :     sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
    2891              : 
    2892              :     /*
    2893              :      * check the current transaction state
    2894              :      */
    2895        34526 :     is_parallel_worker = (s->blockState == TBLOCK_PARALLEL_INPROGRESS);
    2896        34526 :     if (s->state != TRANS_INPROGRESS && s->state != TRANS_PREPARE)
    2897            0 :         elog(WARNING, "AbortTransaction while in %s state",
    2898              :              TransStateAsString(s->state));
    2899              :     Assert(s->parent == NULL);
    2900              : 
    2901              :     /*
    2902              :      * set the current transaction state information appropriately during the
    2903              :      * abort processing
    2904              :      */
    2905        34526 :     s->state = TRANS_ABORT;
    2906              : 
    2907              :     /*
    2908              :      * Reset user ID which might have been changed transiently.  We need this
    2909              :      * to clean up in case control escaped out of a SECURITY DEFINER function
    2910              :      * or other local change of CurrentUserId; therefore, the prior value of
    2911              :      * SecurityRestrictionContext also needs to be restored.
    2912              :      *
    2913              :      * (Note: it is not necessary to restore session authorization or role
    2914              :      * settings here because those can only be changed via GUC, and GUC will
    2915              :      * take care of rolling them back if need be.)
    2916              :      */
    2917        34526 :     SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
    2918              : 
    2919              :     /* Forget about any active REINDEX. */
    2920        34526 :     ResetReindexState(s->nestingLevel);
    2921              : 
    2922              :     /* Reset logical streaming state. */
    2923        34526 :     ResetLogicalStreamingState();
    2924              : 
    2925              :     /* Reset snapshot export state. */
    2926        34526 :     SnapBuildResetExportedSnapshotState();
    2927              : 
    2928              :     /*
    2929              :      * If this xact has started any unfinished parallel operation, clean up
    2930              :      * its workers and exit parallel mode.  Don't warn about leaked resources.
    2931              :      */
    2932        34526 :     AtEOXact_Parallel(false);
    2933        34526 :     s->parallelModeLevel = 0;
    2934        34526 :     s->parallelChildXact = false;    /* should be false already */
    2935              : 
    2936              :     /*
    2937              :      * do abort processing
    2938              :      */
    2939        34526 :     AfterTriggerEndXact(false); /* 'false' means it's abort */
    2940        34526 :     AtAbort_Portals();
    2941        34526 :     smgrDoPendingSyncs(false, is_parallel_worker);
    2942        34526 :     AtEOXact_LargeObject(false);
    2943        34526 :     AtAbort_Notify();
    2944        34526 :     AtEOXact_RelationMap(false, is_parallel_worker);
    2945        34526 :     AtAbort_Twophase();
    2946              : 
    2947              :     /*
    2948              :      * Advertise the fact that we aborted in pg_xact (assuming that we got as
    2949              :      * far as assigning an XID to advertise).  But if we're inside a parallel
    2950              :      * worker, skip this; the user backend must be the one to write the abort
    2951              :      * record.
    2952              :      */
    2953        34526 :     if (!is_parallel_worker)
    2954        34518 :         latestXid = RecordTransactionAbort(false);
    2955              :     else
    2956              :     {
    2957            8 :         latestXid = InvalidTransactionId;
    2958              : 
    2959              :         /*
    2960              :          * Since the parallel leader won't get our value of XactLastRecEnd in
    2961              :          * this case, we nudge WAL-writer ourselves in this case.  See related
    2962              :          * comments in RecordTransactionAbort for why this matters.
    2963              :          */
    2964            8 :         XLogSetAsyncXactLSN(XactLastRecEnd);
    2965              :     }
    2966              : 
    2967              :     TRACE_POSTGRESQL_TRANSACTION_ABORT(MyProc->vxid.lxid);
    2968              : 
    2969              :     /*
    2970              :      * Let others know about no transaction in progress by me. Note that this
    2971              :      * must be done _before_ releasing locks we hold and _after_
    2972              :      * RecordTransactionAbort.
    2973              :      */
    2974        34526 :     ProcArrayEndTransaction(MyProc, latestXid);
    2975              : 
    2976              :     /*
    2977              :      * Post-abort cleanup.  See notes in CommitTransaction() concerning
    2978              :      * ordering.  We can skip all of it if the transaction failed before
    2979              :      * creating a resource owner.
    2980              :      */
    2981        34526 :     if (TopTransactionResourceOwner != NULL)
    2982              :     {
    2983        34526 :         if (is_parallel_worker)
    2984            8 :             CallXactCallbacks(XACT_EVENT_PARALLEL_ABORT);
    2985              :         else
    2986        34518 :             CallXactCallbacks(XACT_EVENT_ABORT);
    2987              : 
    2988        34526 :         ResourceOwnerRelease(TopTransactionResourceOwner,
    2989              :                              RESOURCE_RELEASE_BEFORE_LOCKS,
    2990              :                              false, true);
    2991        34526 :         AtEOXact_Aio(false);
    2992        34526 :         AtEOXact_Buffers(false);
    2993        34526 :         AtEOXact_RelationCache(false);
    2994        34526 :         AtEOXact_TypeCache();
    2995        34526 :         AtEOXact_Inval(false);
    2996        34526 :         AtEOXact_MultiXact();
    2997        34526 :         ResourceOwnerRelease(TopTransactionResourceOwner,
    2998              :                              RESOURCE_RELEASE_LOCKS,
    2999              :                              false, true);
    3000        34526 :         ResourceOwnerRelease(TopTransactionResourceOwner,
    3001              :                              RESOURCE_RELEASE_AFTER_LOCKS,
    3002              :                              false, true);
    3003        34526 :         smgrDoPendingDeletes(false);
    3004              : 
    3005        34526 :         AtEOXact_GUC(false, 1);
    3006        34526 :         AtEOXact_SPI(false);
    3007        34526 :         AtEOXact_Enum();
    3008        34526 :         AtEOXact_on_commit_actions(false);
    3009        34526 :         AtEOXact_Namespace(false, is_parallel_worker);
    3010        34526 :         AtEOXact_SMgr();
    3011        34526 :         AtEOXact_Files(false);
    3012        34526 :         AtEOXact_ComboCid();
    3013        34526 :         AtEOXact_HashTables(false);
    3014        34526 :         AtEOXact_PgStat(false, is_parallel_worker);
    3015        34526 :         AtEOXact_ApplyLauncher(false);
    3016        34526 :         AtEOXact_LogicalRepWorkers(false);
    3017        34526 :         AtEOXact_LogicalCtl();
    3018        34526 :         pgstat_report_xact_timestamp(0);
    3019              :     }
    3020              : 
    3021              :     /*
    3022              :      * State remains TRANS_ABORT until CleanupTransaction().
    3023              :      */
    3024        34526 :     RESUME_INTERRUPTS();
    3025        34526 : }
    3026              : 
    3027              : /*
    3028              :  *  CleanupTransaction
    3029              :  */
    3030              : static void
    3031        34526 : CleanupTransaction(void)
    3032              : {
    3033        34526 :     TransactionState s = CurrentTransactionState;
    3034              : 
    3035              :     /*
    3036              :      * State should still be TRANS_ABORT from AbortTransaction().
    3037              :      */
    3038        34526 :     if (s->state != TRANS_ABORT)
    3039            0 :         elog(FATAL, "CleanupTransaction: unexpected state %s",
    3040              :              TransStateAsString(s->state));
    3041              : 
    3042              :     /*
    3043              :      * do abort cleanup processing
    3044              :      */
    3045        34526 :     AtCleanup_Portals();        /* now safe to release portal memory */
    3046        34526 :     AtEOXact_Snapshot(false, true); /* and release the transaction's snapshots */
    3047              : 
    3048        34526 :     CurrentResourceOwner = NULL;    /* and resource owner */
    3049        34526 :     if (TopTransactionResourceOwner)
    3050        34526 :         ResourceOwnerDelete(TopTransactionResourceOwner);
    3051        34526 :     s->curTransactionOwner = NULL;
    3052        34526 :     CurTransactionResourceOwner = NULL;
    3053        34526 :     TopTransactionResourceOwner = NULL;
    3054              : 
    3055        34526 :     AtCleanup_Memory();         /* and transaction memory */
    3056              : 
    3057        34526 :     s->fullTransactionId = InvalidFullTransactionId;
    3058        34526 :     s->subTransactionId = InvalidSubTransactionId;
    3059        34526 :     s->nestingLevel = 0;
    3060        34526 :     s->gucNestLevel = 0;
    3061        34526 :     s->childXids = NULL;
    3062        34526 :     s->nChildXids = 0;
    3063        34526 :     s->maxChildXids = 0;
    3064        34526 :     s->parallelModeLevel = 0;
    3065        34526 :     s->parallelChildXact = false;
    3066              : 
    3067        34526 :     XactTopFullTransactionId = InvalidFullTransactionId;
    3068        34526 :     nParallelCurrentXids = 0;
    3069              : 
    3070              :     /*
    3071              :      * done with abort processing, set current transaction state back to
    3072              :      * default
    3073              :      */
    3074        34526 :     s->state = TRANS_DEFAULT;
    3075        34526 : }
    3076              : 
    3077              : /*
    3078              :  *  StartTransactionCommand
    3079              :  */
    3080              : void
    3081       718698 : StartTransactionCommand(void)
    3082              : {
    3083       718698 :     TransactionState s = CurrentTransactionState;
    3084              : 
    3085       718698 :     switch (s->blockState)
    3086              :     {
    3087              :             /*
    3088              :              * if we aren't in a transaction block, we just do our usual start
    3089              :              * transaction.
    3090              :              */
    3091       612804 :         case TBLOCK_DEFAULT:
    3092       612804 :             StartTransaction();
    3093       612804 :             s->blockState = TBLOCK_STARTED;
    3094       612804 :             break;
    3095              : 
    3096              :             /*
    3097              :              * We are somewhere in a transaction block or subtransaction and
    3098              :              * about to start a new command.  For now we do nothing, but
    3099              :              * someday we may do command-local resource initialization. (Note
    3100              :              * that any needed CommandCounterIncrement was done by the
    3101              :              * previous CommitTransactionCommand.)
    3102              :              */
    3103       104769 :         case TBLOCK_INPROGRESS:
    3104              :         case TBLOCK_IMPLICIT_INPROGRESS:
    3105              :         case TBLOCK_SUBINPROGRESS:
    3106       104769 :             break;
    3107              : 
    3108              :             /*
    3109              :              * Here we are in a failed transaction block (one of the commands
    3110              :              * caused an abort) so we do nothing but remain in the abort
    3111              :              * state.  Eventually we will get a ROLLBACK command which will
    3112              :              * get us out of this state.  (It is up to other code to ensure
    3113              :              * that no commands other than ROLLBACK will be processed in these
    3114              :              * states.)
    3115              :              */
    3116         1125 :         case TBLOCK_ABORT:
    3117              :         case TBLOCK_SUBABORT:
    3118         1125 :             break;
    3119              : 
    3120              :             /* These cases are invalid. */
    3121            0 :         case TBLOCK_STARTED:
    3122              :         case TBLOCK_BEGIN:
    3123              :         case TBLOCK_PARALLEL_INPROGRESS:
    3124              :         case TBLOCK_SUBBEGIN:
    3125              :         case TBLOCK_END:
    3126              :         case TBLOCK_SUBRELEASE:
    3127              :         case TBLOCK_SUBCOMMIT:
    3128              :         case TBLOCK_ABORT_END:
    3129              :         case TBLOCK_SUBABORT_END:
    3130              :         case TBLOCK_ABORT_PENDING:
    3131              :         case TBLOCK_SUBABORT_PENDING:
    3132              :         case TBLOCK_SUBRESTART:
    3133              :         case TBLOCK_SUBABORT_RESTART:
    3134              :         case TBLOCK_PREPARE:
    3135            0 :             elog(ERROR, "StartTransactionCommand: unexpected state %s",
    3136              :                  BlockStateAsString(s->blockState));
    3137              :             break;
    3138              :     }
    3139              : 
    3140              :     /*
    3141              :      * We must switch to CurTransactionContext before returning. This is
    3142              :      * already done if we called StartTransaction, otherwise not.
    3143              :      */
    3144              :     Assert(CurTransactionContext != NULL);
    3145       718698 :     MemoryContextSwitchTo(CurTransactionContext);
    3146       718698 : }
    3147              : 
    3148              : 
    3149              : /*
    3150              :  * Simple system for saving and restoring transaction characteristics
    3151              :  * (isolation level, read only, deferrable).  We need this for transaction
    3152              :  * chaining, so that we can set the characteristics of the new transaction to
    3153              :  * be the same as the previous one.  (We need something like this because the
    3154              :  * GUC system resets the characteristics at transaction end, so for example
    3155              :  * just skipping the reset in StartTransaction() won't work.)
    3156              :  */
    3157              : void
    3158       686769 : SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)
    3159              : {
    3160       686769 :     s->save_XactIsoLevel = XactIsoLevel;
    3161       686769 :     s->save_XactReadOnly = XactReadOnly;
    3162       686769 :     s->save_XactDeferrable = XactDeferrable;
    3163       686769 : }
    3164              : 
    3165              : void
    3166           44 : RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)
    3167              : {
    3168           44 :     XactIsoLevel = s->save_XactIsoLevel;
    3169           44 :     XactReadOnly = s->save_XactReadOnly;
    3170           44 :     XactDeferrable = s->save_XactDeferrable;
    3171           44 : }
    3172              : 
    3173              : /*
    3174              :  *  CommitTransactionCommand -- a wrapper function handling the
    3175              :  *      loop over subtransactions to avoid a potentially dangerous recursion
    3176              :  *      in CommitTransactionCommandInternal().
    3177              :  */
    3178              : void
    3179       686474 : CommitTransactionCommand(void)
    3180              : {
    3181              :     /*
    3182              :      * Repeatedly call CommitTransactionCommandInternal() until all the work
    3183              :      * is done.
    3184              :      */
    3185       686765 :     while (!CommitTransactionCommandInternal())
    3186              :     {
    3187              :     }
    3188       686146 : }
    3189              : 
    3190              : /*
    3191              :  *  CommitTransactionCommandInternal - a function doing an iteration of work
    3192              :  *      regarding handling the commit transaction command.  In the case of
    3193              :  *      subtransactions more than one iterations could be required.  Returns
    3194              :  *      true when no more iterations required, false otherwise.
    3195              :  */
    3196              : static bool
    3197       686765 : CommitTransactionCommandInternal(void)
    3198              : {
    3199       686765 :     TransactionState s = CurrentTransactionState;
    3200              :     SavedTransactionCharacteristics savetc;
    3201              : 
    3202              :     /* Must save in case we need to restore below */
    3203       686765 :     SaveTransactionCharacteristics(&savetc);
    3204              : 
    3205       686765 :     switch (s->blockState)
    3206              :     {
    3207              :             /*
    3208              :              * These shouldn't happen.  TBLOCK_DEFAULT means the previous
    3209              :              * StartTransactionCommand didn't set the STARTED state
    3210              :              * appropriately, while TBLOCK_PARALLEL_INPROGRESS should be ended
    3211              :              * by EndParallelWorkerTransaction(), not this function.
    3212              :              */
    3213            0 :         case TBLOCK_DEFAULT:
    3214              :         case TBLOCK_PARALLEL_INPROGRESS:
    3215            0 :             elog(FATAL, "CommitTransactionCommand: unexpected state %s",
    3216              :                  BlockStateAsString(s->blockState));
    3217              :             break;
    3218              : 
    3219              :             /*
    3220              :              * If we aren't in a transaction block, just do our usual
    3221              :              * transaction commit, and return to the idle state.
    3222              :              */
    3223       569208 :         case TBLOCK_STARTED:
    3224       569208 :             CommitTransaction();
    3225       569197 :             s->blockState = TBLOCK_DEFAULT;
    3226       569197 :             break;
    3227              : 
    3228              :             /*
    3229              :              * We are completing a "BEGIN TRANSACTION" command, so we change
    3230              :              * to the "transaction block in progress" state and return.  (We
    3231              :              * assume the BEGIN did nothing to the database, so we need no
    3232              :              * CommandCounterIncrement.)
    3233              :              */
    3234        12388 :         case TBLOCK_BEGIN:
    3235        12388 :             s->blockState = TBLOCK_INPROGRESS;
    3236        12388 :             break;
    3237              : 
    3238              :             /*
    3239              :              * This is the case when we have finished executing a command
    3240              :              * someplace within a transaction block.  We increment the command
    3241              :              * counter and return.
    3242              :              */
    3243        80823 :         case TBLOCK_INPROGRESS:
    3244              :         case TBLOCK_IMPLICIT_INPROGRESS:
    3245              :         case TBLOCK_SUBINPROGRESS:
    3246        80823 :             CommandCounterIncrement();
    3247        80823 :             break;
    3248              : 
    3249              :             /*
    3250              :              * We are completing a "COMMIT" command.  Do it and return to the
    3251              :              * idle state.
    3252              :              */
    3253         8647 :         case TBLOCK_END:
    3254         8647 :             CommitTransaction();
    3255         8416 :             s->blockState = TBLOCK_DEFAULT;
    3256         8416 :             if (s->chain)
    3257              :             {
    3258            8 :                 StartTransaction();
    3259            8 :                 s->blockState = TBLOCK_INPROGRESS;
    3260            8 :                 s->chain = false;
    3261            8 :                 RestoreTransactionCharacteristics(&savetc);
    3262              :             }
    3263         8416 :             break;
    3264              : 
    3265              :             /*
    3266              :              * Here we are in the middle of a transaction block but one of the
    3267              :              * commands caused an abort so we do nothing but remain in the
    3268              :              * abort state.  Eventually we will get a ROLLBACK command.
    3269              :              */
    3270           12 :         case TBLOCK_ABORT:
    3271              :         case TBLOCK_SUBABORT:
    3272           12 :             break;
    3273              : 
    3274              :             /*
    3275              :              * Here we were in an aborted transaction block and we just got
    3276              :              * the ROLLBACK command from the user, so clean up the
    3277              :              * already-aborted transaction and return to the idle state.
    3278              :              */
    3279          861 :         case TBLOCK_ABORT_END:
    3280          861 :             CleanupTransaction();
    3281          861 :             s->blockState = TBLOCK_DEFAULT;
    3282          861 :             if (s->chain)
    3283              :             {
    3284            8 :                 StartTransaction();
    3285            8 :                 s->blockState = TBLOCK_INPROGRESS;
    3286            8 :                 s->chain = false;
    3287            8 :                 RestoreTransactionCharacteristics(&savetc);
    3288              :             }
    3289          861 :             break;
    3290              : 
    3291              :             /*
    3292              :              * Here we were in a perfectly good transaction block but the user
    3293              :              * told us to ROLLBACK anyway.  We have to abort the transaction
    3294              :              * and then clean up.
    3295              :              */
    3296         1771 :         case TBLOCK_ABORT_PENDING:
    3297         1771 :             AbortTransaction();
    3298         1771 :             CleanupTransaction();
    3299         1771 :             s->blockState = TBLOCK_DEFAULT;
    3300         1771 :             if (s->chain)
    3301              :             {
    3302           12 :                 StartTransaction();
    3303           12 :                 s->blockState = TBLOCK_INPROGRESS;
    3304           12 :                 s->chain = false;
    3305           12 :                 RestoreTransactionCharacteristics(&savetc);
    3306              :             }
    3307         1771 :             break;
    3308              : 
    3309              :             /*
    3310              :              * We are completing a "PREPARE TRANSACTION" command.  Do it and
    3311              :              * return to the idle state.
    3312              :              */
    3313          285 :         case TBLOCK_PREPARE:
    3314          285 :             PrepareTransaction();
    3315          218 :             s->blockState = TBLOCK_DEFAULT;
    3316          218 :             break;
    3317              : 
    3318              :             /*
    3319              :              * The user issued a SAVEPOINT inside a transaction block. Start a
    3320              :              * subtransaction.  (DefineSavepoint already did PushTransaction,
    3321              :              * so as to have someplace to put the SUBBEGIN state.)
    3322              :              */
    3323        11334 :         case TBLOCK_SUBBEGIN:
    3324        11334 :             StartSubTransaction();
    3325        11334 :             s->blockState = TBLOCK_SUBINPROGRESS;
    3326        11334 :             break;
    3327              : 
    3328              :             /*
    3329              :              * The user issued a RELEASE command, so we end the current
    3330              :              * subtransaction and return to the parent transaction. The parent
    3331              :              * might be ended too, so repeat till we find an INPROGRESS
    3332              :              * transaction or subtransaction.
    3333              :              */
    3334          255 :         case TBLOCK_SUBRELEASE:
    3335              :             do
    3336              :             {
    3337          255 :                 CommitSubTransaction();
    3338          255 :                 s = CurrentTransactionState;    /* changed by pop */
    3339          255 :             } while (s->blockState == TBLOCK_SUBRELEASE);
    3340              : 
    3341              :             Assert(s->blockState == TBLOCK_INPROGRESS ||
    3342              :                    s->blockState == TBLOCK_SUBINPROGRESS);
    3343          168 :             break;
    3344              : 
    3345              :             /*
    3346              :              * The user issued a COMMIT, so we end the current subtransaction
    3347              :              * hierarchy and perform final commit. We do this by rolling up
    3348              :              * any subtransactions into their parent, which leads to O(N^2)
    3349              :              * operations with respect to resource owners - this isn't that
    3350              :              * bad until we approach a thousands of savepoints but is
    3351              :              * necessary for correctness should after triggers create new
    3352              :              * resource owners.
    3353              :              */
    3354          602 :         case TBLOCK_SUBCOMMIT:
    3355              :             do
    3356              :             {
    3357          602 :                 CommitSubTransaction();
    3358          602 :                 s = CurrentTransactionState;    /* changed by pop */
    3359          602 :             } while (s->blockState == TBLOCK_SUBCOMMIT);
    3360              :             /* If we had a COMMIT command, finish off the main xact too */
    3361          514 :             if (s->blockState == TBLOCK_END)
    3362              :             {
    3363              :                 Assert(s->parent == NULL);
    3364          413 :                 CommitTransaction();
    3365          396 :                 s->blockState = TBLOCK_DEFAULT;
    3366          396 :                 if (s->chain)
    3367              :                 {
    3368           12 :                     StartTransaction();
    3369           12 :                     s->blockState = TBLOCK_INPROGRESS;
    3370           12 :                     s->chain = false;
    3371           12 :                     RestoreTransactionCharacteristics(&savetc);
    3372              :                 }
    3373              :             }
    3374          101 :             else if (s->blockState == TBLOCK_PREPARE)
    3375              :             {
    3376              :                 Assert(s->parent == NULL);
    3377          101 :                 PrepareTransaction();
    3378           99 :                 s->blockState = TBLOCK_DEFAULT;
    3379              :             }
    3380              :             else
    3381            0 :                 elog(ERROR, "CommitTransactionCommand: unexpected state %s",
    3382              :                      BlockStateAsString(s->blockState));
    3383          495 :             break;
    3384              : 
    3385              :             /*
    3386              :              * The current already-failed subtransaction is ending due to a
    3387              :              * ROLLBACK or ROLLBACK TO command, so pop it and recursively
    3388              :              * examine the parent (which could be in any of several states).
    3389              :              * As we need to examine the parent, return false to request the
    3390              :              * caller to do the next iteration.
    3391              :              */
    3392           55 :         case TBLOCK_SUBABORT_END:
    3393           55 :             CleanupSubTransaction();
    3394           55 :             return false;
    3395              : 
    3396              :             /*
    3397              :              * As above, but it's not dead yet, so abort first.
    3398              :              */
    3399          236 :         case TBLOCK_SUBABORT_PENDING:
    3400          236 :             AbortSubTransaction();
    3401          236 :             CleanupSubTransaction();
    3402          236 :             return false;
    3403              : 
    3404              :             /*
    3405              :              * The current subtransaction is the target of a ROLLBACK TO
    3406              :              * command.  Abort and pop it, then start a new subtransaction
    3407              :              * with the same name.
    3408              :              */
    3409          329 :         case TBLOCK_SUBRESTART:
    3410              :             {
    3411              :                 char       *name;
    3412              :                 int         savepointLevel;
    3413              : 
    3414              :                 /* save name and keep Cleanup from freeing it */
    3415          329 :                 name = s->name;
    3416          329 :                 s->name = NULL;
    3417          329 :                 savepointLevel = s->savepointLevel;
    3418              : 
    3419          329 :                 AbortSubTransaction();
    3420          329 :                 CleanupSubTransaction();
    3421              : 
    3422          329 :                 DefineSavepoint(NULL);
    3423          329 :                 s = CurrentTransactionState;    /* changed by push */
    3424          329 :                 s->name = name;
    3425          329 :                 s->savepointLevel = savepointLevel;
    3426              : 
    3427              :                 /* This is the same as TBLOCK_SUBBEGIN case */
    3428              :                 Assert(s->blockState == TBLOCK_SUBBEGIN);
    3429          329 :                 StartSubTransaction();
    3430          329 :                 s->blockState = TBLOCK_SUBINPROGRESS;
    3431              :             }
    3432          329 :             break;
    3433              : 
    3434              :             /*
    3435              :              * Same as above, but the subtransaction had already failed, so we
    3436              :              * don't need AbortSubTransaction.
    3437              :              */
    3438          134 :         case TBLOCK_SUBABORT_RESTART:
    3439              :             {
    3440              :                 char       *name;
    3441              :                 int         savepointLevel;
    3442              : 
    3443              :                 /* save name and keep Cleanup from freeing it */
    3444          134 :                 name = s->name;
    3445          134 :                 s->name = NULL;
    3446          134 :                 savepointLevel = s->savepointLevel;
    3447              : 
    3448          134 :                 CleanupSubTransaction();
    3449              : 
    3450          134 :                 DefineSavepoint(NULL);
    3451          134 :                 s = CurrentTransactionState;    /* changed by push */
    3452          134 :                 s->name = name;
    3453          134 :                 s->savepointLevel = savepointLevel;
    3454              : 
    3455              :                 /* This is the same as TBLOCK_SUBBEGIN case */
    3456              :                 Assert(s->blockState == TBLOCK_SUBBEGIN);
    3457          134 :                 StartSubTransaction();
    3458          134 :                 s->blockState = TBLOCK_SUBINPROGRESS;
    3459              :             }
    3460          134 :             break;
    3461              :     }
    3462              : 
    3463              :     /* Done, no more iterations required */
    3464       686146 :     return true;
    3465              : }
    3466              : 
    3467              : /*
    3468              :  *  AbortCurrentTransaction -- a wrapper function handling the
    3469              :  *      loop over subtransactions to avoid potentially dangerous recursion in
    3470              :  *      AbortCurrentTransactionInternal().
    3471              :  */
    3472              : void
    3473        33269 : AbortCurrentTransaction(void)
    3474              : {
    3475              :     /*
    3476              :      * Repeatedly call AbortCurrentTransactionInternal() until all the work is
    3477              :      * done.
    3478              :      */
    3479        33269 :     while (!AbortCurrentTransactionInternal())
    3480              :     {
    3481              :     }
    3482        33269 : }
    3483              : 
    3484              : /*
    3485              :  *  AbortCurrentTransactionInternal - a function doing an iteration of work
    3486              :  *      regarding handling the current transaction abort.  In the case of
    3487              :  *      subtransactions more than one iterations could be required.  Returns
    3488              :  *      true when no more iterations required, false otherwise.
    3489              :  */
    3490              : static bool
    3491        33269 : AbortCurrentTransactionInternal(void)
    3492              : {
    3493        33269 :     TransactionState s = CurrentTransactionState;
    3494              : 
    3495        33269 :     switch (s->blockState)
    3496              :     {
    3497           49 :         case TBLOCK_DEFAULT:
    3498           49 :             if (s->state == TRANS_DEFAULT)
    3499              :             {
    3500              :                 /* we are idle, so nothing to do */
    3501              :             }
    3502              :             else
    3503              :             {
    3504              :                 /*
    3505              :                  * We can get here after an error during transaction start
    3506              :                  * (state will be TRANS_START).  Need to clean up the
    3507              :                  * incompletely started transaction.  First, adjust the
    3508              :                  * low-level state to suppress warning message from
    3509              :                  * AbortTransaction.
    3510              :                  */
    3511            0 :                 if (s->state == TRANS_START)
    3512            0 :                     s->state = TRANS_INPROGRESS;
    3513            0 :                 AbortTransaction();
    3514            0 :                 CleanupTransaction();
    3515              :             }
    3516           49 :             break;
    3517              : 
    3518              :             /*
    3519              :              * If we aren't in a transaction block, we just do the basic abort
    3520              :              * & cleanup transaction.  For this purpose, we treat an implicit
    3521              :              * transaction block as if it were a simple statement.
    3522              :              */
    3523        30845 :         case TBLOCK_STARTED:
    3524              :         case TBLOCK_IMPLICIT_INPROGRESS:
    3525        30845 :             AbortTransaction();
    3526        30845 :             CleanupTransaction();
    3527        30845 :             s->blockState = TBLOCK_DEFAULT;
    3528        30845 :             break;
    3529              : 
    3530              :             /*
    3531              :              * If we are in TBLOCK_BEGIN it means something screwed up right
    3532              :              * after reading "BEGIN TRANSACTION".  We assume that the user
    3533              :              * will interpret the error as meaning the BEGIN failed to get him
    3534              :              * into a transaction block, so we should abort and return to idle
    3535              :              * state.
    3536              :              */
    3537            0 :         case TBLOCK_BEGIN:
    3538            0 :             AbortTransaction();
    3539            0 :             CleanupTransaction();
    3540            0 :             s->blockState = TBLOCK_DEFAULT;
    3541            0 :             break;
    3542              : 
    3543              :             /*
    3544              :              * We are somewhere in a transaction block and we've gotten a
    3545              :              * failure, so we abort the transaction and set up the persistent
    3546              :              * ABORT state.  We will stay in ABORT until we get a ROLLBACK.
    3547              :              */
    3548          875 :         case TBLOCK_INPROGRESS:
    3549              :         case TBLOCK_PARALLEL_INPROGRESS:
    3550          875 :             AbortTransaction();
    3551          875 :             s->blockState = TBLOCK_ABORT;
    3552              :             /* CleanupTransaction happens when we exit TBLOCK_ABORT_END */
    3553          875 :             break;
    3554              : 
    3555              :             /*
    3556              :              * Here, we failed while trying to COMMIT.  Clean up the
    3557              :              * transaction and return to idle state (we do not want to stay in
    3558              :              * the transaction).
    3559              :              */
    3560          248 :         case TBLOCK_END:
    3561          248 :             AbortTransaction();
    3562          248 :             CleanupTransaction();
    3563          248 :             s->blockState = TBLOCK_DEFAULT;
    3564          248 :             break;
    3565              : 
    3566              :             /*
    3567              :              * Here, we are already in an aborted transaction state and are
    3568              :              * waiting for a ROLLBACK, but for some reason we failed again! So
    3569              :              * we just remain in the abort state.
    3570              :              */
    3571           64 :         case TBLOCK_ABORT:
    3572              :         case TBLOCK_SUBABORT:
    3573           64 :             break;
    3574              : 
    3575              :             /*
    3576              :              * We are in a failed transaction and we got the ROLLBACK command.
    3577              :              * We have already aborted, we just need to cleanup and go to idle
    3578              :              * state.
    3579              :              */
    3580            0 :         case TBLOCK_ABORT_END:
    3581            0 :             CleanupTransaction();
    3582            0 :             s->blockState = TBLOCK_DEFAULT;
    3583            0 :             break;
    3584              : 
    3585              :             /*
    3586              :              * We are in a live transaction and we got a ROLLBACK command.
    3587              :              * Abort, cleanup, go to idle state.
    3588              :              */
    3589            0 :         case TBLOCK_ABORT_PENDING:
    3590            0 :             AbortTransaction();
    3591            0 :             CleanupTransaction();
    3592            0 :             s->blockState = TBLOCK_DEFAULT;
    3593            0 :             break;
    3594              : 
    3595              :             /*
    3596              :              * Here, we failed while trying to PREPARE.  Clean up the
    3597              :              * transaction and return to idle state (we do not want to stay in
    3598              :              * the transaction).
    3599              :              */
    3600           64 :         case TBLOCK_PREPARE:
    3601           64 :             AbortTransaction();
    3602           64 :             CleanupTransaction();
    3603           64 :             s->blockState = TBLOCK_DEFAULT;
    3604           64 :             break;
    3605              : 
    3606              :             /*
    3607              :              * We got an error inside a subtransaction.  Abort just the
    3608              :              * subtransaction, and go to the persistent SUBABORT state until
    3609              :              * we get ROLLBACK.
    3610              :              */
    3611         1124 :         case TBLOCK_SUBINPROGRESS:
    3612         1124 :             AbortSubTransaction();
    3613         1124 :             s->blockState = TBLOCK_SUBABORT;
    3614         1124 :             break;
    3615              : 
    3616              :             /*
    3617              :              * If we failed while trying to create a subtransaction, clean up
    3618              :              * the broken subtransaction and abort the parent.  The same
    3619              :              * applies if we get a failure while ending a subtransaction.  As
    3620              :              * we need to abort the parent, return false to request the caller
    3621              :              * to do the next iteration.
    3622              :              */
    3623            0 :         case TBLOCK_SUBBEGIN:
    3624              :         case TBLOCK_SUBRELEASE:
    3625              :         case TBLOCK_SUBCOMMIT:
    3626              :         case TBLOCK_SUBABORT_PENDING:
    3627              :         case TBLOCK_SUBRESTART:
    3628            0 :             AbortSubTransaction();
    3629            0 :             CleanupSubTransaction();
    3630            0 :             return false;
    3631              : 
    3632              :             /*
    3633              :              * Same as above, except the Abort() was already done.
    3634              :              */
    3635            0 :         case TBLOCK_SUBABORT_END:
    3636              :         case TBLOCK_SUBABORT_RESTART:
    3637            0 :             CleanupSubTransaction();
    3638            0 :             return false;
    3639              :     }
    3640              : 
    3641              :     /* Done, no more iterations required */
    3642        33269 :     return true;
    3643              : }
    3644              : 
    3645              : /*
    3646              :  *  PreventInTransactionBlock
    3647              :  *
    3648              :  *  This routine is to be called by statements that must not run inside
    3649              :  *  a transaction block, typically because they have non-rollback-able
    3650              :  *  side effects or do internal commits.
    3651              :  *
    3652              :  *  If this routine completes successfully, then the calling statement is
    3653              :  *  guaranteed that if it completes without error, its results will be
    3654              :  *  committed immediately.
    3655              :  *
    3656              :  *  If we have already started a transaction block, issue an error; also issue
    3657              :  *  an error if we appear to be running inside a user-defined function (which
    3658              :  *  could issue more commands and possibly cause a failure after the statement
    3659              :  *  completes).  Subtransactions are verboten too.
    3660              :  *
    3661              :  *  We must also set XACT_FLAGS_NEEDIMMEDIATECOMMIT in MyXactFlags, to ensure
    3662              :  *  that postgres.c follows through by committing after the statement is done.
    3663              :  *
    3664              :  *  isTopLevel: passed down from ProcessUtility to determine whether we are
    3665              :  *  inside a function.  (We will always fail if this is false, but it's
    3666              :  *  convenient to centralize the check here instead of making callers do it.)
    3667              :  *  stmtType: statement type name, for error messages.
    3668              :  */
    3669              : void
    3670       109953 : PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
    3671              : {
    3672              :     /*
    3673              :      * xact block already started?
    3674              :      */
    3675       109953 :     if (IsTransactionBlock())
    3676           78 :         ereport(ERROR,
    3677              :                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3678              :         /* translator: %s represents an SQL statement name */
    3679              :                  errmsg("%s cannot run inside a transaction block",
    3680              :                         stmtType)));
    3681              : 
    3682              :     /*
    3683              :      * subtransaction?
    3684              :      */
    3685       109875 :     if (IsSubTransaction())
    3686            0 :         ereport(ERROR,
    3687              :                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3688              :         /* translator: %s represents an SQL statement name */
    3689              :                  errmsg("%s cannot run inside a subtransaction",
    3690              :                         stmtType)));
    3691              : 
    3692              :     /*
    3693              :      * inside a function call?
    3694              :      */
    3695       109875 :     if (!isTopLevel)
    3696            4 :         ereport(ERROR,
    3697              :                 (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3698              :         /* translator: %s represents an SQL statement name */
    3699              :                  errmsg("%s cannot be executed from a function or procedure",
    3700              :                         stmtType)));
    3701              : 
    3702              :     /* If we got past IsTransactionBlock test, should be in default state */
    3703       109871 :     if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
    3704       108904 :         CurrentTransactionState->blockState != TBLOCK_STARTED)
    3705            0 :         elog(FATAL, "cannot prevent transaction chain");
    3706              : 
    3707              :     /* All okay.  Set the flag to make sure the right thing happens later. */
    3708       109871 :     MyXactFlags |= XACT_FLAGS_NEEDIMMEDIATECOMMIT;
    3709       109871 : }
    3710              : 
    3711              : /*
    3712              :  *  WarnNoTransactionBlock
    3713              :  *  RequireTransactionBlock
    3714              :  *
    3715              :  *  These two functions allow for warnings or errors if a command is executed
    3716              :  *  outside of a transaction block.  This is useful for commands that have no
    3717              :  *  effects that persist past transaction end (and so calling them outside a
    3718              :  *  transaction block is presumably an error).  DECLARE CURSOR is an example.
    3719              :  *  While top-level transaction control commands (BEGIN/COMMIT/ABORT) and SET
    3720              :  *  that have no effect issue warnings, all other no-effect commands generate
    3721              :  *  errors.
    3722              :  *
    3723              :  *  If we appear to be running inside a user-defined function, we do not
    3724              :  *  issue anything, since the function could issue more commands that make
    3725              :  *  use of the current statement's results.  Likewise subtransactions.
    3726              :  *  Thus these are inverses for PreventInTransactionBlock.
    3727              :  *
    3728              :  *  isTopLevel: passed down from ProcessUtility to determine whether we are
    3729              :  *  inside a function.
    3730              :  *  stmtType: statement type name, for warning or error messages.
    3731              :  */
    3732              : void
    3733         1460 : WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
    3734              : {
    3735         1460 :     CheckTransactionBlock(isTopLevel, false, stmtType);
    3736         1460 : }
    3737              : 
    3738              : void
    3739         5028 : RequireTransactionBlock(bool isTopLevel, const char *stmtType)
    3740              : {
    3741         5028 :     CheckTransactionBlock(isTopLevel, true, stmtType);
    3742         5005 : }
    3743              : 
    3744              : /*
    3745              :  * This is the implementation of the above two.
    3746              :  */
    3747              : static void
    3748         6488 : CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
    3749              : {
    3750              :     /*
    3751              :      * xact block already started?
    3752              :      */
    3753         6488 :     if (IsTransactionBlock())
    3754         6369 :         return;
    3755              : 
    3756              :     /*
    3757              :      * subtransaction?
    3758              :      */
    3759          119 :     if (IsSubTransaction())
    3760            0 :         return;
    3761              : 
    3762              :     /*
    3763              :      * inside a function call?
    3764              :      */
    3765          119 :     if (!isTopLevel)
    3766           82 :         return;
    3767              : 
    3768           37 :     ereport(throwError ? ERROR : WARNING,
    3769              :             (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    3770              :     /* translator: %s represents an SQL statement name */
    3771              :              errmsg("%s can only be used in transaction blocks",
    3772              :                     stmtType)));
    3773              : }
    3774              : 
    3775              : /*
    3776              :  *  IsInTransactionBlock
    3777              :  *
    3778              :  *  This routine is for statements that need to behave differently inside
    3779              :  *  a transaction block than when running as single commands.  ANALYZE is
    3780              :  *  currently the only example.
    3781              :  *
    3782              :  *  If this routine returns "false", then the calling statement is allowed
    3783              :  *  to perform internal transaction-commit-and-start cycles; there is not a
    3784              :  *  risk of messing up any transaction already in progress.  (Note that this
    3785              :  *  is not the identical guarantee provided by PreventInTransactionBlock,
    3786              :  *  since we will not force a post-statement commit.)
    3787              :  *
    3788              :  *  isTopLevel: passed down from ProcessUtility to determine whether we are
    3789              :  *  inside a function.
    3790              :  */
    3791              : bool
    3792         3092 : IsInTransactionBlock(bool isTopLevel)
    3793              : {
    3794              :     /*
    3795              :      * Return true on same conditions that would make
    3796              :      * PreventInTransactionBlock error out
    3797              :      */
    3798         3092 :     if (IsTransactionBlock())
    3799           98 :         return true;
    3800              : 
    3801         2994 :     if (IsSubTransaction())
    3802            0 :         return true;
    3803              : 
    3804         2994 :     if (!isTopLevel)
    3805           74 :         return true;
    3806              : 
    3807         2920 :     if (CurrentTransactionState->blockState != TBLOCK_DEFAULT &&
    3808         2920 :         CurrentTransactionState->blockState != TBLOCK_STARTED)
    3809            0 :         return true;
    3810              : 
    3811         2920 :     return false;
    3812              : }
    3813              : 
    3814              : 
    3815              : /*
    3816              :  * Register or deregister callback functions for start- and end-of-xact
    3817              :  * operations.
    3818              :  *
    3819              :  * These functions are intended for use by dynamically loaded modules.
    3820              :  * For built-in modules we generally just hardwire the appropriate calls
    3821              :  * (mainly because it's easier to control the order that way, where needed).
    3822              :  *
    3823              :  * At transaction end, the callback occurs post-commit or post-abort, so the
    3824              :  * callback functions can only do noncritical cleanup.
    3825              :  */
    3826              : void
    3827         2323 : RegisterXactCallback(XactCallback callback, void *arg)
    3828              : {
    3829              :     XactCallbackItem *item;
    3830              : 
    3831              :     item = (XactCallbackItem *)
    3832         2323 :         MemoryContextAlloc(TopMemoryContext, sizeof(XactCallbackItem));
    3833         2323 :     item->callback = callback;
    3834         2323 :     item->arg = arg;
    3835         2323 :     item->next = Xact_callbacks;
    3836         2323 :     Xact_callbacks = item;
    3837         2323 : }
    3838              : 
    3839              : void
    3840            0 : UnregisterXactCallback(XactCallback callback, void *arg)
    3841              : {
    3842              :     XactCallbackItem *item;
    3843              :     XactCallbackItem *prev;
    3844              : 
    3845            0 :     prev = NULL;
    3846            0 :     for (item = Xact_callbacks; item; prev = item, item = item->next)
    3847              :     {
    3848            0 :         if (item->callback == callback && item->arg == arg)
    3849              :         {
    3850            0 :             if (prev)
    3851            0 :                 prev->next = item->next;
    3852              :             else
    3853            0 :                 Xact_callbacks = item->next;
    3854            0 :             pfree(item);
    3855            0 :             break;
    3856              :         }
    3857              :     }
    3858            0 : }
    3859              : 
    3860              : static void
    3861      1195388 : CallXactCallbacks(XactEvent event)
    3862              : {
    3863              :     XactCallbackItem *item;
    3864              :     XactCallbackItem *next;
    3865              : 
    3866      1396428 :     for (item = Xact_callbacks; item; item = next)
    3867              :     {
    3868              :         /* allow callbacks to unregister themselves when called */
    3869       201041 :         next = item->next;
    3870       201041 :         item->callback(event, item->arg);
    3871              :     }
    3872      1195387 : }
    3873              : 
    3874              : 
    3875              : /*
    3876              :  * Register or deregister callback functions for start- and end-of-subxact
    3877              :  * operations.
    3878              :  *
    3879              :  * Pretty much same as above, but for subtransaction events.
    3880              :  *
    3881              :  * At subtransaction end, the callback occurs post-subcommit or post-subabort,
    3882              :  * so the callback functions can only do noncritical cleanup.  At
    3883              :  * subtransaction start, the callback is called when the subtransaction has
    3884              :  * finished initializing.
    3885              :  */
    3886              : void
    3887         2323 : RegisterSubXactCallback(SubXactCallback callback, void *arg)
    3888              : {
    3889              :     SubXactCallbackItem *item;
    3890              : 
    3891              :     item = (SubXactCallbackItem *)
    3892         2323 :         MemoryContextAlloc(TopMemoryContext, sizeof(SubXactCallbackItem));
    3893         2323 :     item->callback = callback;
    3894         2323 :     item->arg = arg;
    3895         2323 :     item->next = SubXact_callbacks;
    3896         2323 :     SubXact_callbacks = item;
    3897         2323 : }
    3898              : 
    3899              : void
    3900            0 : UnregisterSubXactCallback(SubXactCallback callback, void *arg)
    3901              : {
    3902              :     SubXactCallbackItem *item;
    3903              :     SubXactCallbackItem *prev;
    3904              : 
    3905            0 :     prev = NULL;
    3906            0 :     for (item = SubXact_callbacks; item; prev = item, item = item->next)
    3907              :     {
    3908            0 :         if (item->callback == callback && item->arg == arg)
    3909              :         {
    3910            0 :             if (prev)
    3911            0 :                 prev->next = item->next;
    3912              :             else
    3913            0 :                 SubXact_callbacks = item->next;
    3914            0 :             pfree(item);
    3915            0 :             break;
    3916              :         }
    3917              :     }
    3918            0 : }
    3919              : 
    3920              : static void
    3921        29449 : CallSubXactCallbacks(SubXactEvent event,
    3922              :                      SubTransactionId mySubid,
    3923              :                      SubTransactionId parentSubid)
    3924              : {
    3925              :     SubXactCallbackItem *item;
    3926              :     SubXactCallbackItem *next;
    3927              : 
    3928        53063 :     for (item = SubXact_callbacks; item; item = next)
    3929              :     {
    3930              :         /* allow callbacks to unregister themselves when called */
    3931        23614 :         next = item->next;
    3932        23614 :         item->callback(event, mySubid, parentSubid, item->arg);
    3933              :     }
    3934        29449 : }
    3935              : 
    3936              : 
    3937              : /* ----------------------------------------------------------------
    3938              :  *                     transaction block support
    3939              :  * ----------------------------------------------------------------
    3940              :  */
    3941              : 
    3942              : /*
    3943              :  *  BeginTransactionBlock
    3944              :  *      This executes a BEGIN command.
    3945              :  */
    3946              : void
    3947        12388 : BeginTransactionBlock(void)
    3948              : {
    3949        12388 :     TransactionState s = CurrentTransactionState;
    3950              : 
    3951        12388 :     switch (s->blockState)
    3952              :     {
    3953              :             /*
    3954              :              * We are not inside a transaction block, so allow one to begin.
    3955              :              */
    3956        11889 :         case TBLOCK_STARTED:
    3957        11889 :             s->blockState = TBLOCK_BEGIN;
    3958        11889 :             break;
    3959              : 
    3960              :             /*
    3961              :              * BEGIN converts an implicit transaction block to a regular one.
    3962              :              * (Note that we allow this even if we've already done some
    3963              :              * commands, which is a bit odd but matches historical practice.)
    3964              :              */
    3965          499 :         case TBLOCK_IMPLICIT_INPROGRESS:
    3966          499 :             s->blockState = TBLOCK_BEGIN;
    3967          499 :             break;
    3968              : 
    3969              :             /*
    3970              :              * Already a transaction block in progress.
    3971              :              */
    3972            0 :         case TBLOCK_INPROGRESS:
    3973              :         case TBLOCK_PARALLEL_INPROGRESS:
    3974              :         case TBLOCK_SUBINPROGRESS:
    3975              :         case TBLOCK_ABORT:
    3976              :         case TBLOCK_SUBABORT:
    3977            0 :             ereport(WARNING,
    3978              :                     (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION),
    3979              :                      errmsg("there is already a transaction in progress")));
    3980            0 :             break;
    3981              : 
    3982              :             /* These cases are invalid. */
    3983            0 :         case TBLOCK_DEFAULT:
    3984              :         case TBLOCK_BEGIN:
    3985              :         case TBLOCK_SUBBEGIN:
    3986              :         case TBLOCK_END:
    3987              :         case TBLOCK_SUBRELEASE:
    3988              :         case TBLOCK_SUBCOMMIT:
    3989              :         case TBLOCK_ABORT_END:
    3990              :         case TBLOCK_SUBABORT_END:
    3991              :         case TBLOCK_ABORT_PENDING:
    3992              :         case TBLOCK_SUBABORT_PENDING:
    3993              :         case TBLOCK_SUBRESTART:
    3994              :         case TBLOCK_SUBABORT_RESTART:
    3995              :         case TBLOCK_PREPARE:
    3996            0 :             elog(FATAL, "BeginTransactionBlock: unexpected state %s",
    3997              :                  BlockStateAsString(s->blockState));
    3998              :             break;
    3999              :     }
    4000        12388 : }
    4001              : 
    4002              : /*
    4003              :  *  PrepareTransactionBlock
    4004              :  *      This executes a PREPARE command.
    4005              :  *
    4006              :  * Since PREPARE may actually do a ROLLBACK, the result indicates what
    4007              :  * happened: true for PREPARE, false for ROLLBACK.
    4008              :  *
    4009              :  * Note that we don't actually do anything here except change blockState.
    4010              :  * The real work will be done in the upcoming PrepareTransaction().
    4011              :  * We do it this way because it's not convenient to change memory context,
    4012              :  * resource owner, etc while executing inside a Portal.
    4013              :  */
    4014              : bool
    4015          388 : PrepareTransactionBlock(const char *gid)
    4016              : {
    4017              :     TransactionState s;
    4018              :     bool        result;
    4019              : 
    4020              :     /* Set up to commit the current transaction */
    4021          388 :     result = EndTransactionBlock(false);
    4022              : 
    4023              :     /* If successful, change outer tblock state to PREPARE */
    4024          388 :     if (result)
    4025              :     {
    4026          386 :         s = CurrentTransactionState;
    4027              : 
    4028          497 :         while (s->parent != NULL)
    4029          111 :             s = s->parent;
    4030              : 
    4031          386 :         if (s->blockState == TBLOCK_END)
    4032              :         {
    4033              :             /* Save GID where PrepareTransaction can find it again */
    4034          386 :             prepareGID = MemoryContextStrdup(TopTransactionContext, gid);
    4035              : 
    4036          386 :             s->blockState = TBLOCK_PREPARE;
    4037              :         }
    4038              :         else
    4039              :         {
    4040              :             /*
    4041              :              * ignore case where we are not in a transaction;
    4042              :              * EndTransactionBlock already issued a warning.
    4043              :              */
    4044              :             Assert(s->blockState == TBLOCK_STARTED ||
    4045              :                    s->blockState == TBLOCK_IMPLICIT_INPROGRESS);
    4046              :             /* Don't send back a PREPARE result tag... */
    4047            0 :             result = false;
    4048              :         }
    4049              :     }
    4050              : 
    4051          388 :     return result;
    4052              : }
    4053              : 
    4054              : /*
    4055              :  *  EndTransactionBlock
    4056              :  *      This executes a COMMIT command.
    4057              :  *
    4058              :  * Since COMMIT may actually do a ROLLBACK, the result indicates what
    4059              :  * happened: true for COMMIT, false for ROLLBACK.
    4060              :  *
    4061              :  * Note that we don't actually do anything here except change blockState.
    4062              :  * The real work will be done in the upcoming CommitTransactionCommand().
    4063              :  * We do it this way because it's not convenient to change memory context,
    4064              :  * resource owner, etc while executing inside a Portal.
    4065              :  */
    4066              : bool
    4067         9946 : EndTransactionBlock(bool chain)
    4068              : {
    4069         9946 :     TransactionState s = CurrentTransactionState;
    4070         9946 :     bool        result = false;
    4071              : 
    4072         9946 :     switch (s->blockState)
    4073              :     {
    4074              :             /*
    4075              :              * We are in a transaction block, so tell CommitTransactionCommand
    4076              :              * to COMMIT.
    4077              :              */
    4078         8916 :         case TBLOCK_INPROGRESS:
    4079         8916 :             s->blockState = TBLOCK_END;
    4080         8916 :             result = true;
    4081         8916 :             break;
    4082              : 
    4083              :             /*
    4084              :              * We are in an implicit transaction block.  If AND CHAIN was
    4085              :              * specified, error.  Otherwise commit, but issue a warning
    4086              :              * because there was no explicit BEGIN before this.
    4087              :              */
    4088           32 :         case TBLOCK_IMPLICIT_INPROGRESS:
    4089           32 :             if (chain)
    4090           16 :                 ereport(ERROR,
    4091              :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4092              :                 /* translator: %s represents an SQL statement name */
    4093              :                          errmsg("%s can only be used in transaction blocks",
    4094              :                                 "COMMIT AND CHAIN")));
    4095              :             else
    4096           16 :                 ereport(WARNING,
    4097              :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4098              :                          errmsg("there is no transaction in progress")));
    4099           16 :             s->blockState = TBLOCK_END;
    4100           16 :             result = true;
    4101           16 :             break;
    4102              : 
    4103              :             /*
    4104              :              * We are in a failed transaction block.  Tell
    4105              :              * CommitTransactionCommand it's time to exit the block.
    4106              :              */
    4107          430 :         case TBLOCK_ABORT:
    4108          430 :             s->blockState = TBLOCK_ABORT_END;
    4109          430 :             break;
    4110              : 
    4111              :             /*
    4112              :              * We are in a live subtransaction block.  Set up to subcommit all
    4113              :              * open subtransactions and then commit the main transaction.
    4114              :              */
    4115          514 :         case TBLOCK_SUBINPROGRESS:
    4116         1116 :             while (s->parent != NULL)
    4117              :             {
    4118          602 :                 if (s->blockState == TBLOCK_SUBINPROGRESS)
    4119          602 :                     s->blockState = TBLOCK_SUBCOMMIT;
    4120              :                 else
    4121            0 :                     elog(FATAL, "EndTransactionBlock: unexpected state %s",
    4122              :                          BlockStateAsString(s->blockState));
    4123          602 :                 s = s->parent;
    4124              :             }
    4125          514 :             if (s->blockState == TBLOCK_INPROGRESS)
    4126          514 :                 s->blockState = TBLOCK_END;
    4127              :             else
    4128            0 :                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
    4129              :                      BlockStateAsString(s->blockState));
    4130          514 :             result = true;
    4131          514 :             break;
    4132              : 
    4133              :             /*
    4134              :              * Here we are inside an aborted subtransaction.  Treat the COMMIT
    4135              :              * as ROLLBACK: set up to abort everything and exit the main
    4136              :              * transaction.
    4137              :              */
    4138           38 :         case TBLOCK_SUBABORT:
    4139           76 :             while (s->parent != NULL)
    4140              :             {
    4141           38 :                 if (s->blockState == TBLOCK_SUBINPROGRESS)
    4142            0 :                     s->blockState = TBLOCK_SUBABORT_PENDING;
    4143           38 :                 else if (s->blockState == TBLOCK_SUBABORT)
    4144           38 :                     s->blockState = TBLOCK_SUBABORT_END;
    4145              :                 else
    4146            0 :                     elog(FATAL, "EndTransactionBlock: unexpected state %s",
    4147              :                          BlockStateAsString(s->blockState));
    4148           38 :                 s = s->parent;
    4149              :             }
    4150           38 :             if (s->blockState == TBLOCK_INPROGRESS)
    4151           38 :                 s->blockState = TBLOCK_ABORT_PENDING;
    4152            0 :             else if (s->blockState == TBLOCK_ABORT)
    4153            0 :                 s->blockState = TBLOCK_ABORT_END;
    4154              :             else
    4155            0 :                 elog(FATAL, "EndTransactionBlock: unexpected state %s",
    4156              :                      BlockStateAsString(s->blockState));
    4157           38 :             break;
    4158              : 
    4159              :             /*
    4160              :              * The user issued COMMIT when not inside a transaction.  For
    4161              :              * COMMIT without CHAIN, issue a WARNING, staying in
    4162              :              * TBLOCK_STARTED state.  The upcoming call to
    4163              :              * CommitTransactionCommand() will then close the transaction and
    4164              :              * put us back into the default state.  For COMMIT AND CHAIN,
    4165              :              * error.
    4166              :              */
    4167           16 :         case TBLOCK_STARTED:
    4168           16 :             if (chain)
    4169            4 :                 ereport(ERROR,
    4170              :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4171              :                 /* translator: %s represents an SQL statement name */
    4172              :                          errmsg("%s can only be used in transaction blocks",
    4173              :                                 "COMMIT AND CHAIN")));
    4174              :             else
    4175           12 :                 ereport(WARNING,
    4176              :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4177              :                          errmsg("there is no transaction in progress")));
    4178           12 :             result = true;
    4179           12 :             break;
    4180              : 
    4181              :             /*
    4182              :              * The user issued a COMMIT that somehow ran inside a parallel
    4183              :              * worker.  We can't cope with that.
    4184              :              */
    4185            0 :         case TBLOCK_PARALLEL_INPROGRESS:
    4186            0 :             ereport(FATAL,
    4187              :                     (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4188              :                      errmsg("cannot commit during a parallel operation")));
    4189              :             break;
    4190              : 
    4191              :             /* These cases are invalid. */
    4192            0 :         case TBLOCK_DEFAULT:
    4193              :         case TBLOCK_BEGIN:
    4194              :         case TBLOCK_SUBBEGIN:
    4195              :         case TBLOCK_END:
    4196              :         case TBLOCK_SUBRELEASE:
    4197              :         case TBLOCK_SUBCOMMIT:
    4198              :         case TBLOCK_ABORT_END:
    4199              :         case TBLOCK_SUBABORT_END:
    4200              :         case TBLOCK_ABORT_PENDING:
    4201              :         case TBLOCK_SUBABORT_PENDING:
    4202              :         case TBLOCK_SUBRESTART:
    4203              :         case TBLOCK_SUBABORT_RESTART:
    4204              :         case TBLOCK_PREPARE:
    4205            0 :             elog(FATAL, "EndTransactionBlock: unexpected state %s",
    4206              :                  BlockStateAsString(s->blockState));
    4207              :             break;
    4208              :     }
    4209              : 
    4210              :     Assert(s->blockState == TBLOCK_STARTED ||
    4211              :            s->blockState == TBLOCK_END ||
    4212              :            s->blockState == TBLOCK_ABORT_END ||
    4213              :            s->blockState == TBLOCK_ABORT_PENDING);
    4214              : 
    4215         9926 :     s->chain = chain;
    4216              : 
    4217         9926 :     return result;
    4218              : }
    4219              : 
    4220              : /*
    4221              :  *  UserAbortTransactionBlock
    4222              :  *      This executes a ROLLBACK command.
    4223              :  *
    4224              :  * As above, we don't actually do anything here except change blockState.
    4225              :  */
    4226              : void
    4227         2184 : UserAbortTransactionBlock(bool chain)
    4228              : {
    4229         2184 :     TransactionState s = CurrentTransactionState;
    4230              : 
    4231         2184 :     switch (s->blockState)
    4232              :     {
    4233              :             /*
    4234              :              * We are inside a transaction block and we got a ROLLBACK command
    4235              :              * from the user, so tell CommitTransactionCommand to abort and
    4236              :              * exit the transaction block.
    4237              :              */
    4238         1627 :         case TBLOCK_INPROGRESS:
    4239         1627 :             s->blockState = TBLOCK_ABORT_PENDING;
    4240         1627 :             break;
    4241              : 
    4242              :             /*
    4243              :              * We are inside a failed transaction block and we got a ROLLBACK
    4244              :              * command from the user.  Abort processing is already done, so
    4245              :              * CommitTransactionCommand just has to cleanup and go back to
    4246              :              * idle state.
    4247              :              */
    4248          431 :         case TBLOCK_ABORT:
    4249          431 :             s->blockState = TBLOCK_ABORT_END;
    4250          431 :             break;
    4251              : 
    4252              :             /*
    4253              :              * We are inside a subtransaction.  Mark everything up to top
    4254              :              * level as exitable.
    4255              :              */
    4256           75 :         case TBLOCK_SUBINPROGRESS:
    4257              :         case TBLOCK_SUBABORT:
    4258          290 :             while (s->parent != NULL)
    4259              :             {
    4260          215 :                 if (s->blockState == TBLOCK_SUBINPROGRESS)
    4261          198 :                     s->blockState = TBLOCK_SUBABORT_PENDING;
    4262           17 :                 else if (s->blockState == TBLOCK_SUBABORT)
    4263           17 :                     s->blockState = TBLOCK_SUBABORT_END;
    4264              :                 else
    4265            0 :                     elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
    4266              :                          BlockStateAsString(s->blockState));
    4267          215 :                 s = s->parent;
    4268              :             }
    4269           75 :             if (s->blockState == TBLOCK_INPROGRESS)
    4270           75 :                 s->blockState = TBLOCK_ABORT_PENDING;
    4271            0 :             else if (s->blockState == TBLOCK_ABORT)
    4272            0 :                 s->blockState = TBLOCK_ABORT_END;
    4273              :             else
    4274            0 :                 elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
    4275              :                      BlockStateAsString(s->blockState));
    4276           75 :             break;
    4277              : 
    4278              :             /*
    4279              :              * The user issued ABORT when not inside a transaction.  For
    4280              :              * ROLLBACK without CHAIN, issue a WARNING and go to abort state.
    4281              :              * The upcoming call to CommitTransactionCommand() will then put
    4282              :              * us back into the default state.  For ROLLBACK AND CHAIN, error.
    4283              :              *
    4284              :              * We do the same thing with ABORT inside an implicit transaction,
    4285              :              * although in this case we might be rolling back actual database
    4286              :              * state changes.  (It's debatable whether we should issue a
    4287              :              * WARNING in this case, but we have done so historically.)
    4288              :              */
    4289           51 :         case TBLOCK_STARTED:
    4290              :         case TBLOCK_IMPLICIT_INPROGRESS:
    4291           51 :             if (chain)
    4292           20 :                 ereport(ERROR,
    4293              :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4294              :                 /* translator: %s represents an SQL statement name */
    4295              :                          errmsg("%s can only be used in transaction blocks",
    4296              :                                 "ROLLBACK AND CHAIN")));
    4297              :             else
    4298           31 :                 ereport(WARNING,
    4299              :                         (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4300              :                          errmsg("there is no transaction in progress")));
    4301           31 :             s->blockState = TBLOCK_ABORT_PENDING;
    4302           31 :             break;
    4303              : 
    4304              :             /*
    4305              :              * The user issued an ABORT that somehow ran inside a parallel
    4306              :              * worker.  We can't cope with that.
    4307              :              */
    4308            0 :         case TBLOCK_PARALLEL_INPROGRESS:
    4309            0 :             ereport(FATAL,
    4310              :                     (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4311              :                      errmsg("cannot abort during a parallel operation")));
    4312              :             break;
    4313              : 
    4314              :             /* These cases are invalid. */
    4315            0 :         case TBLOCK_DEFAULT:
    4316              :         case TBLOCK_BEGIN:
    4317              :         case TBLOCK_SUBBEGIN:
    4318              :         case TBLOCK_END:
    4319              :         case TBLOCK_SUBRELEASE:
    4320              :         case TBLOCK_SUBCOMMIT:
    4321              :         case TBLOCK_ABORT_END:
    4322              :         case TBLOCK_SUBABORT_END:
    4323              :         case TBLOCK_ABORT_PENDING:
    4324              :         case TBLOCK_SUBABORT_PENDING:
    4325              :         case TBLOCK_SUBRESTART:
    4326              :         case TBLOCK_SUBABORT_RESTART:
    4327              :         case TBLOCK_PREPARE:
    4328            0 :             elog(FATAL, "UserAbortTransactionBlock: unexpected state %s",
    4329              :                  BlockStateAsString(s->blockState));
    4330              :             break;
    4331              :     }
    4332              : 
    4333              :     Assert(s->blockState == TBLOCK_ABORT_END ||
    4334              :            s->blockState == TBLOCK_ABORT_PENDING);
    4335              : 
    4336         2164 :     s->chain = chain;
    4337         2164 : }
    4338              : 
    4339              : /*
    4340              :  * BeginImplicitTransactionBlock
    4341              :  *      Start an implicit transaction block if we're not already in one.
    4342              :  *
    4343              :  * Unlike BeginTransactionBlock, this is called directly from the main loop
    4344              :  * in postgres.c, not within a Portal.  So we can just change blockState
    4345              :  * without a lot of ceremony.  We do not expect caller to do
    4346              :  * CommitTransactionCommand/StartTransactionCommand.
    4347              :  */
    4348              : void
    4349        46501 : BeginImplicitTransactionBlock(void)
    4350              : {
    4351        46501 :     TransactionState s = CurrentTransactionState;
    4352              : 
    4353              :     /*
    4354              :      * If we are in STARTED state (that is, no transaction block is open),
    4355              :      * switch to IMPLICIT_INPROGRESS state, creating an implicit transaction
    4356              :      * block.
    4357              :      *
    4358              :      * For caller convenience, we consider all other transaction states as
    4359              :      * legal here; otherwise the caller would need its own state check, which
    4360              :      * seems rather pointless.
    4361              :      */
    4362        46501 :     if (s->blockState == TBLOCK_STARTED)
    4363         5547 :         s->blockState = TBLOCK_IMPLICIT_INPROGRESS;
    4364        46501 : }
    4365              : 
    4366              : /*
    4367              :  * EndImplicitTransactionBlock
    4368              :  *      End an implicit transaction block, if we're in one.
    4369              :  *
    4370              :  * Like EndTransactionBlock, we just make any needed blockState change here.
    4371              :  * The real work will be done in the upcoming CommitTransactionCommand().
    4372              :  */
    4373              : void
    4374        18490 : EndImplicitTransactionBlock(void)
    4375              : {
    4376        18490 :     TransactionState s = CurrentTransactionState;
    4377              : 
    4378              :     /*
    4379              :      * If we are in IMPLICIT_INPROGRESS state, switch back to STARTED state,
    4380              :      * allowing CommitTransactionCommand to commit whatever happened during
    4381              :      * the implicit transaction block as though it were a single statement.
    4382              :      *
    4383              :      * For caller convenience, we consider all other transaction states as
    4384              :      * legal here; otherwise the caller would need its own state check, which
    4385              :      * seems rather pointless.
    4386              :      */
    4387        18490 :     if (s->blockState == TBLOCK_IMPLICIT_INPROGRESS)
    4388         4936 :         s->blockState = TBLOCK_STARTED;
    4389        18490 : }
    4390              : 
    4391              : /*
    4392              :  * DefineSavepoint
    4393              :  *      This executes a SAVEPOINT command.
    4394              :  */
    4395              : void
    4396         1619 : DefineSavepoint(const char *name)
    4397              : {
    4398         1619 :     TransactionState s = CurrentTransactionState;
    4399              : 
    4400              :     /*
    4401              :      * Workers synchronize transaction state at the beginning of each parallel
    4402              :      * operation, so we can't account for new subtransactions after that
    4403              :      * point.  (Note that this check will certainly error out if s->blockState
    4404              :      * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
    4405              :      * below.)
    4406              :      */
    4407         1619 :     if (IsInParallelMode() || IsParallelWorker())
    4408            0 :         ereport(ERROR,
    4409              :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4410              :                  errmsg("cannot define savepoints during a parallel operation")));
    4411              : 
    4412         1619 :     switch (s->blockState)
    4413              :     {
    4414         1611 :         case TBLOCK_INPROGRESS:
    4415              :         case TBLOCK_SUBINPROGRESS:
    4416              :             /* Normal subtransaction start */
    4417         1611 :             PushTransaction();
    4418         1611 :             s = CurrentTransactionState;    /* changed by push */
    4419              : 
    4420              :             /*
    4421              :              * Savepoint names, like the TransactionState block itself, live
    4422              :              * in TopTransactionContext.
    4423              :              */
    4424         1611 :             if (name)
    4425         1148 :                 s->name = MemoryContextStrdup(TopTransactionContext, name);
    4426         1611 :             break;
    4427              : 
    4428              :             /*
    4429              :              * We disallow savepoint commands in implicit transaction blocks.
    4430              :              * There would be no great difficulty in allowing them so far as
    4431              :              * this module is concerned, but a savepoint seems inconsistent
    4432              :              * with exec_simple_query's behavior of abandoning the whole query
    4433              :              * string upon error.  Also, the point of an implicit transaction
    4434              :              * block (as opposed to a regular one) is to automatically close
    4435              :              * after an error, so it's hard to see how a savepoint would fit
    4436              :              * into that.
    4437              :              *
    4438              :              * The error messages for this are phrased as if there were no
    4439              :              * active transaction block at all, which is historical but
    4440              :              * perhaps could be improved.
    4441              :              */
    4442            8 :         case TBLOCK_IMPLICIT_INPROGRESS:
    4443            8 :             ereport(ERROR,
    4444              :                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4445              :             /* translator: %s represents an SQL statement name */
    4446              :                      errmsg("%s can only be used in transaction blocks",
    4447              :                             "SAVEPOINT")));
    4448              :             break;
    4449              : 
    4450              :             /* These cases are invalid. */
    4451            0 :         case TBLOCK_DEFAULT:
    4452              :         case TBLOCK_STARTED:
    4453              :         case TBLOCK_BEGIN:
    4454              :         case TBLOCK_PARALLEL_INPROGRESS:
    4455              :         case TBLOCK_SUBBEGIN:
    4456              :         case TBLOCK_END:
    4457              :         case TBLOCK_SUBRELEASE:
    4458              :         case TBLOCK_SUBCOMMIT:
    4459              :         case TBLOCK_ABORT:
    4460              :         case TBLOCK_SUBABORT:
    4461              :         case TBLOCK_ABORT_END:
    4462              :         case TBLOCK_SUBABORT_END:
    4463              :         case TBLOCK_ABORT_PENDING:
    4464              :         case TBLOCK_SUBABORT_PENDING:
    4465              :         case TBLOCK_SUBRESTART:
    4466              :         case TBLOCK_SUBABORT_RESTART:
    4467              :         case TBLOCK_PREPARE:
    4468            0 :             elog(FATAL, "DefineSavepoint: unexpected state %s",
    4469              :                  BlockStateAsString(s->blockState));
    4470              :             break;
    4471              :     }
    4472         1611 : }
    4473              : 
    4474              : /*
    4475              :  * ReleaseSavepoint
    4476              :  *      This executes a RELEASE command.
    4477              :  *
    4478              :  * As above, we don't actually do anything here except change blockState.
    4479              :  */
    4480              : void
    4481          172 : ReleaseSavepoint(const char *name)
    4482              : {
    4483          172 :     TransactionState s = CurrentTransactionState;
    4484              :     TransactionState target,
    4485              :                 xact;
    4486              : 
    4487              :     /*
    4488              :      * Workers synchronize transaction state at the beginning of each parallel
    4489              :      * operation, so we can't account for transaction state change after that
    4490              :      * point.  (Note that this check will certainly error out if s->blockState
    4491              :      * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
    4492              :      * below.)
    4493              :      */
    4494          172 :     if (IsInParallelMode() || IsParallelWorker())
    4495            0 :         ereport(ERROR,
    4496              :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4497              :                  errmsg("cannot release savepoints during a parallel operation")));
    4498              : 
    4499          172 :     switch (s->blockState)
    4500              :     {
    4501              :             /*
    4502              :              * We can't release a savepoint if there is no savepoint defined.
    4503              :              */
    4504            0 :         case TBLOCK_INPROGRESS:
    4505            0 :             ereport(ERROR,
    4506              :                     (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4507              :                      errmsg("savepoint \"%s\" does not exist", name)));
    4508              :             break;
    4509              : 
    4510            4 :         case TBLOCK_IMPLICIT_INPROGRESS:
    4511              :             /* See comment about implicit transactions in DefineSavepoint */
    4512            4 :             ereport(ERROR,
    4513              :                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4514              :             /* translator: %s represents an SQL statement name */
    4515              :                      errmsg("%s can only be used in transaction blocks",
    4516              :                             "RELEASE SAVEPOINT")));
    4517              :             break;
    4518              : 
    4519              :             /*
    4520              :              * We are in a non-aborted subtransaction.  This is the only valid
    4521              :              * case.
    4522              :              */
    4523          168 :         case TBLOCK_SUBINPROGRESS:
    4524          168 :             break;
    4525              : 
    4526              :             /* These cases are invalid. */
    4527            0 :         case TBLOCK_DEFAULT:
    4528              :         case TBLOCK_STARTED:
    4529              :         case TBLOCK_BEGIN:
    4530              :         case TBLOCK_PARALLEL_INPROGRESS:
    4531              :         case TBLOCK_SUBBEGIN:
    4532              :         case TBLOCK_END:
    4533              :         case TBLOCK_SUBRELEASE:
    4534              :         case TBLOCK_SUBCOMMIT:
    4535              :         case TBLOCK_ABORT:
    4536              :         case TBLOCK_SUBABORT:
    4537              :         case TBLOCK_ABORT_END:
    4538              :         case TBLOCK_SUBABORT_END:
    4539              :         case TBLOCK_ABORT_PENDING:
    4540              :         case TBLOCK_SUBABORT_PENDING:
    4541              :         case TBLOCK_SUBRESTART:
    4542              :         case TBLOCK_SUBABORT_RESTART:
    4543              :         case TBLOCK_PREPARE:
    4544            0 :             elog(FATAL, "ReleaseSavepoint: unexpected state %s",
    4545              :                  BlockStateAsString(s->blockState));
    4546              :             break;
    4547              :     }
    4548              : 
    4549          255 :     for (target = s; target; target = target->parent)
    4550              :     {
    4551          255 :         if (target->name && strcmp(target->name, name) == 0)
    4552          168 :             break;
    4553              :     }
    4554              : 
    4555          168 :     if (!target)
    4556            0 :         ereport(ERROR,
    4557              :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4558              :                  errmsg("savepoint \"%s\" does not exist", name)));
    4559              : 
    4560              :     /* disallow crossing savepoint level boundaries */
    4561          168 :     if (target->savepointLevel != s->savepointLevel)
    4562            0 :         ereport(ERROR,
    4563              :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4564              :                  errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
    4565              : 
    4566              :     /*
    4567              :      * Mark "commit pending" all subtransactions up to the target
    4568              :      * subtransaction.  The actual commits will happen when control gets to
    4569              :      * CommitTransactionCommand.
    4570              :      */
    4571          168 :     xact = CurrentTransactionState;
    4572              :     for (;;)
    4573              :     {
    4574           87 :         Assert(xact->blockState == TBLOCK_SUBINPROGRESS);
    4575          255 :         xact->blockState = TBLOCK_SUBRELEASE;
    4576          255 :         if (xact == target)
    4577          168 :             break;
    4578           87 :         xact = xact->parent;
    4579              :         Assert(xact);
    4580              :     }
    4581          168 : }
    4582              : 
    4583              : /*
    4584              :  * RollbackToSavepoint
    4585              :  *      This executes a ROLLBACK TO <savepoint> command.
    4586              :  *
    4587              :  * As above, we don't actually do anything here except change blockState.
    4588              :  */
    4589              : void
    4590          471 : RollbackToSavepoint(const char *name)
    4591              : {
    4592          471 :     TransactionState s = CurrentTransactionState;
    4593              :     TransactionState target,
    4594              :                 xact;
    4595              : 
    4596              :     /*
    4597              :      * Workers synchronize transaction state at the beginning of each parallel
    4598              :      * operation, so we can't account for transaction state change after that
    4599              :      * point.  (Note that this check will certainly error out if s->blockState
    4600              :      * is TBLOCK_PARALLEL_INPROGRESS, so we can treat that as an invalid case
    4601              :      * below.)
    4602              :      */
    4603          471 :     if (IsInParallelMode() || IsParallelWorker())
    4604            0 :         ereport(ERROR,
    4605              :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
    4606              :                  errmsg("cannot rollback to savepoints during a parallel operation")));
    4607              : 
    4608          471 :     switch (s->blockState)
    4609              :     {
    4610              :             /*
    4611              :              * We can't rollback to a savepoint if there is no savepoint
    4612              :              * defined.
    4613              :              */
    4614            4 :         case TBLOCK_INPROGRESS:
    4615              :         case TBLOCK_ABORT:
    4616            4 :             ereport(ERROR,
    4617              :                     (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4618              :                      errmsg("savepoint \"%s\" does not exist", name)));
    4619              :             break;
    4620              : 
    4621            4 :         case TBLOCK_IMPLICIT_INPROGRESS:
    4622              :             /* See comment about implicit transactions in DefineSavepoint */
    4623            4 :             ereport(ERROR,
    4624              :                     (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION),
    4625              :             /* translator: %s represents an SQL statement name */
    4626              :                      errmsg("%s can only be used in transaction blocks",
    4627              :                             "ROLLBACK TO SAVEPOINT")));
    4628              :             break;
    4629              : 
    4630              :             /*
    4631              :              * There is at least one savepoint, so proceed.
    4632              :              */
    4633          463 :         case TBLOCK_SUBINPROGRESS:
    4634              :         case TBLOCK_SUBABORT:
    4635          463 :             break;
    4636              : 
    4637              :             /* These cases are invalid. */
    4638            0 :         case TBLOCK_DEFAULT:
    4639              :         case TBLOCK_STARTED:
    4640              :         case TBLOCK_BEGIN:
    4641              :         case TBLOCK_PARALLEL_INPROGRESS:
    4642              :         case TBLOCK_SUBBEGIN:
    4643              :         case TBLOCK_END:
    4644              :         case TBLOCK_SUBRELEASE:
    4645              :         case TBLOCK_SUBCOMMIT:
    4646              :         case TBLOCK_ABORT_END:
    4647              :         case TBLOCK_SUBABORT_END:
    4648              :         case TBLOCK_ABORT_PENDING:
    4649              :         case TBLOCK_SUBABORT_PENDING:
    4650              :         case TBLOCK_SUBRESTART:
    4651              :         case TBLOCK_SUBABORT_RESTART:
    4652              :         case TBLOCK_PREPARE:
    4653            0 :             elog(FATAL, "RollbackToSavepoint: unexpected state %s",
    4654              :                  BlockStateAsString(s->blockState));
    4655              :             break;
    4656              :     }
    4657              : 
    4658          501 :     for (target = s; target; target = target->parent)
    4659              :     {
    4660          501 :         if (target->name && strcmp(target->name, name) == 0)
    4661          463 :             break;
    4662              :     }
    4663              : 
    4664          463 :     if (!target)
    4665            0 :         ereport(ERROR,
    4666              :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4667              :                  errmsg("savepoint \"%s\" does not exist", name)));
    4668              : 
    4669              :     /* disallow crossing savepoint level boundaries */
    4670          463 :     if (target->savepointLevel != s->savepointLevel)
    4671            0 :         ereport(ERROR,
    4672              :                 (errcode(ERRCODE_S_E_INVALID_SPECIFICATION),
    4673              :                  errmsg("savepoint \"%s\" does not exist within current savepoint level", name)));
    4674              : 
    4675              :     /*
    4676              :      * Mark "abort pending" all subtransactions up to the target
    4677              :      * subtransaction.  The actual aborts will happen when control gets to
    4678              :      * CommitTransactionCommand.
    4679              :      */
    4680          463 :     xact = CurrentTransactionState;
    4681              :     for (;;)
    4682              :     {
    4683          501 :         if (xact == target)
    4684          463 :             break;
    4685           38 :         if (xact->blockState == TBLOCK_SUBINPROGRESS)
    4686           38 :             xact->blockState = TBLOCK_SUBABORT_PENDING;
    4687            0 :         else if (xact->blockState == TBLOCK_SUBABORT)
    4688            0 :             xact->blockState = TBLOCK_SUBABORT_END;
    4689              :         else
    4690            0 :             elog(FATAL, "RollbackToSavepoint: unexpected state %s",
    4691              :                  BlockStateAsString(xact->blockState));
    4692           38 :         xact = xact->parent;
    4693              :         Assert(xact);
    4694              :     }
    4695              : 
    4696              :     /* And mark the target as "restart pending" */
    4697          463 :     if (xact->blockState == TBLOCK_SUBINPROGRESS)
    4698          329 :         xact->blockState = TBLOCK_SUBRESTART;
    4699          134 :     else if (xact->blockState == TBLOCK_SUBABORT)
    4700          134 :         xact->blockState = TBLOCK_SUBABORT_RESTART;
    4701              :     else
    4702            0 :         elog(FATAL, "RollbackToSavepoint: unexpected state %s",
    4703              :              BlockStateAsString(xact->blockState));
    4704          463 : }
    4705              : 
    4706              : /*
    4707              :  * BeginInternalSubTransaction
    4708              :  *      This is the same as DefineSavepoint except it allows TBLOCK_STARTED,
    4709              :  *      TBLOCK_IMPLICIT_INPROGRESS, TBLOCK_PARALLEL_INPROGRESS, TBLOCK_END,
    4710              :  *      and TBLOCK_PREPARE states, and therefore it can safely be used in
    4711              :  *      functions that might be called when not inside a BEGIN block or when
    4712              :  *      running deferred triggers at COMMIT/PREPARE time.  Also, it
    4713              :  *      automatically does CommitTransactionCommand/StartTransactionCommand
    4714              :  *      instead of expecting the caller to do it.
    4715              :  */
    4716              : void
    4717        10186 : BeginInternalSubTransaction(const char *name)
    4718              : {
    4719        10186 :     TransactionState s = CurrentTransactionState;
    4720        10186 :     bool        save_ExitOnAnyError = ExitOnAnyError;
    4721              : 
    4722              :     /*
    4723              :      * Errors within this function are improbable, but if one does happen we
    4724              :      * force a FATAL exit.  Callers generally aren't prepared to handle losing
    4725              :      * control, and moreover our transaction state is probably corrupted if we
    4726              :      * fail partway through; so an ordinary ERROR longjmp isn't okay.
    4727              :      */
    4728        10186 :     ExitOnAnyError = true;
    4729              : 
    4730              :     /*
    4731              :      * We do not check for parallel mode here.  It's permissible to start and
    4732              :      * end "internal" subtransactions while in parallel mode, so long as no
    4733              :      * new XIDs or command IDs are assigned.  Enforcement of that occurs in
    4734              :      * AssignTransactionId() and CommandCounterIncrement().
    4735              :      */
    4736              : 
    4737        10186 :     switch (s->blockState)
    4738              :     {
    4739        10186 :         case TBLOCK_STARTED:
    4740              :         case TBLOCK_INPROGRESS:
    4741              :         case TBLOCK_IMPLICIT_INPROGRESS:
    4742              :         case TBLOCK_PARALLEL_INPROGRESS:
    4743              :         case TBLOCK_END:
    4744              :         case TBLOCK_PREPARE:
    4745              :         case TBLOCK_SUBINPROGRESS:
    4746              :             /* Normal subtransaction start */
    4747        10186 :             PushTransaction();
    4748        10186 :             s = CurrentTransactionState;    /* changed by push */
    4749              : 
    4750              :             /*
    4751              :              * Savepoint names, like the TransactionState block itself, live
    4752              :              * in TopTransactionContext.
    4753              :              */
    4754        10186 :             if (name)
    4755          935 :                 s->name = MemoryContextStrdup(TopTransactionContext, name);
    4756        10186 :             break;
    4757              : 
    4758              :             /* These cases are invalid. */
    4759            0 :         case TBLOCK_DEFAULT:
    4760              :         case TBLOCK_BEGIN:
    4761              :         case TBLOCK_SUBBEGIN:
    4762              :         case TBLOCK_SUBRELEASE:
    4763              :         case TBLOCK_SUBCOMMIT:
    4764              :         case TBLOCK_ABORT:
    4765              :         case TBLOCK_SUBABORT:
    4766              :         case TBLOCK_ABORT_END:
    4767              :         case TBLOCK_SUBABORT_END:
    4768              :         case TBLOCK_ABORT_PENDING:
    4769              :         case TBLOCK_SUBABORT_PENDING:
    4770              :         case TBLOCK_SUBRESTART:
    4771              :         case TBLOCK_SUBABORT_RESTART:
    4772            0 :             elog(FATAL, "BeginInternalSubTransaction: unexpected state %s",
    4773              :                  BlockStateAsString(s->blockState));
    4774              :             break;
    4775              :     }
    4776              : 
    4777        10186 :     CommitTransactionCommand();
    4778        10186 :     StartTransactionCommand();
    4779              : 
    4780        10186 :     ExitOnAnyError = save_ExitOnAnyError;
    4781        10186 : }
    4782              : 
    4783              : /*
    4784              :  * ReleaseCurrentSubTransaction
    4785              :  *
    4786              :  * RELEASE (ie, commit) the innermost subtransaction, regardless of its
    4787              :  * savepoint name (if any).
    4788              :  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
    4789              :  */
    4790              : void
    4791         4998 : ReleaseCurrentSubTransaction(void)
    4792              : {
    4793         4998 :     TransactionState s = CurrentTransactionState;
    4794              : 
    4795              :     /*
    4796              :      * We do not check for parallel mode here.  It's permissible to start and
    4797              :      * end "internal" subtransactions while in parallel mode, so long as no
    4798              :      * new XIDs or command IDs are assigned.
    4799              :      */
    4800              : 
    4801         4998 :     if (s->blockState != TBLOCK_SUBINPROGRESS)
    4802            0 :         elog(ERROR, "ReleaseCurrentSubTransaction: unexpected state %s",
    4803              :              BlockStateAsString(s->blockState));
    4804              :     Assert(s->state == TRANS_INPROGRESS);
    4805         4998 :     MemoryContextSwitchTo(CurTransactionContext);
    4806         4998 :     CommitSubTransaction();
    4807         4998 :     s = CurrentTransactionState;    /* changed by pop */
    4808              :     Assert(s->state == TRANS_INPROGRESS);
    4809         4998 : }
    4810              : 
    4811              : /*
    4812              :  * RollbackAndReleaseCurrentSubTransaction
    4813              :  *
    4814              :  * ROLLBACK and RELEASE (ie, abort) the innermost subtransaction, regardless
    4815              :  * of its savepoint name (if any).
    4816              :  * NB: do NOT use CommitTransactionCommand/StartTransactionCommand with this.
    4817              :  */
    4818              : void
    4819         5188 : RollbackAndReleaseCurrentSubTransaction(void)
    4820              : {
    4821         5188 :     TransactionState s = CurrentTransactionState;
    4822              : 
    4823              :     /*
    4824              :      * We do not check for parallel mode here.  It's permissible to start and
    4825              :      * end "internal" subtransactions while in parallel mode, so long as no
    4826              :      * new XIDs or command IDs are assigned.
    4827              :      */
    4828              : 
    4829         5188 :     switch (s->blockState)
    4830              :     {
    4831              :             /* Must be in a subtransaction */
    4832         5188 :         case TBLOCK_SUBINPROGRESS:
    4833              :         case TBLOCK_SUBABORT:
    4834         5188 :             break;
    4835              : 
    4836              :             /* These cases are invalid. */
    4837            0 :         case TBLOCK_DEFAULT:
    4838              :         case TBLOCK_STARTED:
    4839              :         case TBLOCK_BEGIN:
    4840              :         case TBLOCK_IMPLICIT_INPROGRESS:
    4841              :         case TBLOCK_PARALLEL_INPROGRESS:
    4842              :         case TBLOCK_SUBBEGIN:
    4843              :         case TBLOCK_INPROGRESS:
    4844              :         case TBLOCK_END:
    4845              :         case TBLOCK_SUBRELEASE:
    4846              :         case TBLOCK_SUBCOMMIT:
    4847              :         case TBLOCK_ABORT:
    4848              :         case TBLOCK_ABORT_END:
    4849              :         case TBLOCK_SUBABORT_END:
    4850              :         case TBLOCK_ABORT_PENDING:
    4851              :         case TBLOCK_SUBABORT_PENDING:
    4852              :         case TBLOCK_SUBRESTART:
    4853              :         case TBLOCK_SUBABORT_RESTART:
    4854              :         case TBLOCK_PREPARE:
    4855            0 :             elog(FATAL, "RollbackAndReleaseCurrentSubTransaction: unexpected state %s",
    4856              :                  BlockStateAsString(s->blockState));
    4857              :             break;
    4858              :     }
    4859              : 
    4860              :     /*
    4861              :      * Abort the current subtransaction, if needed.
    4862              :      */
    4863         5188 :     if (s->blockState == TBLOCK_SUBINPROGRESS)
    4864         4253 :         AbortSubTransaction();
    4865              : 
    4866              :     /* And clean it up, too */
    4867         5188 :     CleanupSubTransaction();
    4868              : 
    4869         5188 :     s = CurrentTransactionState;    /* changed by pop */
    4870              :     Assert(s->blockState == TBLOCK_SUBINPROGRESS ||
    4871              :            s->blockState == TBLOCK_INPROGRESS ||
    4872              :            s->blockState == TBLOCK_IMPLICIT_INPROGRESS ||
    4873              :            s->blockState == TBLOCK_PARALLEL_INPROGRESS ||
    4874              :            s->blockState == TBLOCK_STARTED);
    4875         5188 : }
    4876              : 
    4877              : /*
    4878              :  *  AbortOutOfAnyTransaction
    4879              :  *
    4880              :  *  This routine is provided for error recovery purposes.  It aborts any
    4881              :  *  active transaction or transaction block, leaving the system in a known
    4882              :  *  idle state.
    4883              :  */
    4884              : void
    4885        19787 : AbortOutOfAnyTransaction(void)
    4886              : {
    4887        19787 :     TransactionState s = CurrentTransactionState;
    4888              : 
    4889              :     /* Ensure we're not running in a doomed memory context */
    4890        19787 :     AtAbort_Memory();
    4891              : 
    4892              :     /*
    4893              :      * Get out of any transaction or nested transaction
    4894              :      */
    4895              :     do
    4896              :     {
    4897        19787 :         switch (s->blockState)
    4898              :         {
    4899        19050 :             case TBLOCK_DEFAULT:
    4900        19050 :                 if (s->state == TRANS_DEFAULT)
    4901              :                 {
    4902              :                     /* Not in a transaction, do nothing */
    4903              :                 }
    4904              :                 else
    4905              :                 {
    4906              :                     /*
    4907              :                      * We can get here after an error during transaction start
    4908              :                      * (state will be TRANS_START).  Need to clean up the
    4909              :                      * incompletely started transaction.  First, adjust the
    4910              :                      * low-level state to suppress warning message from
    4911              :                      * AbortTransaction.
    4912              :                      */
    4913            0 :                     if (s->state == TRANS_START)
    4914            0 :                         s->state = TRANS_INPROGRESS;
    4915            0 :                     AbortTransaction();
    4916            0 :                     CleanupTransaction();
    4917              :                 }
    4918        19050 :                 break;
    4919          723 :             case TBLOCK_STARTED:
    4920              :             case TBLOCK_BEGIN:
    4921              :             case TBLOCK_INPROGRESS:
    4922              :             case TBLOCK_IMPLICIT_INPROGRESS:
    4923              :             case TBLOCK_PARALLEL_INPROGRESS:
    4924              :             case TBLOCK_END:
    4925              :             case TBLOCK_ABORT_PENDING:
    4926              :             case TBLOCK_PREPARE:
    4927              :                 /* In a transaction, so clean up */
    4928          723 :                 AbortTransaction();
    4929          723 :                 CleanupTransaction();
    4930          723 :                 s->blockState = TBLOCK_DEFAULT;
    4931          723 :                 break;
    4932           14 :             case TBLOCK_ABORT:
    4933              :             case TBLOCK_ABORT_END:
    4934              : 
    4935              :                 /*
    4936              :                  * AbortTransaction is already done, still need Cleanup.
    4937              :                  * However, if we failed partway through running ROLLBACK,
    4938              :                  * there will be an active portal running that command, which
    4939              :                  * we need to shut down before doing CleanupTransaction.
    4940              :                  */
    4941           14 :                 AtAbort_Portals();
    4942           14 :                 CleanupTransaction();
    4943           14 :                 s->blockState = TBLOCK_DEFAULT;
    4944           14 :                 break;
    4945              : 
    4946              :                 /*
    4947              :                  * In a subtransaction, so clean it up and abort parent too
    4948              :                  */
    4949            0 :             case TBLOCK_SUBBEGIN:
    4950              :             case TBLOCK_SUBINPROGRESS:
    4951              :             case TBLOCK_SUBRELEASE:
    4952              :             case TBLOCK_SUBCOMMIT:
    4953              :             case TBLOCK_SUBABORT_PENDING:
    4954              :             case TBLOCK_SUBRESTART:
    4955            0 :                 AbortSubTransaction();
    4956            0 :                 CleanupSubTransaction();
    4957            0 :                 s = CurrentTransactionState;    /* changed by pop */
    4958            0 :                 break;
    4959              : 
    4960            0 :             case TBLOCK_SUBABORT:
    4961              :             case TBLOCK_SUBABORT_END:
    4962              :             case TBLOCK_SUBABORT_RESTART:
    4963              :                 /* As above, but AbortSubTransaction already done */
    4964            0 :                 if (s->curTransactionOwner)
    4965              :                 {
    4966              :                     /* As in TBLOCK_ABORT, might have a live portal to zap */
    4967            0 :                     AtSubAbort_Portals(s->subTransactionId,
    4968            0 :                                        s->parent->subTransactionId,
    4969              :                                        s->curTransactionOwner,
    4970            0 :                                        s->parent->curTransactionOwner);
    4971              :                 }
    4972            0 :                 CleanupSubTransaction();
    4973            0 :                 s = CurrentTransactionState;    /* changed by pop */
    4974            0 :                 break;
    4975              :         }
    4976        19787 :     } while (s->blockState != TBLOCK_DEFAULT);
    4977              : 
    4978              :     /* Should be out of all subxacts now */
    4979              :     Assert(s->parent == NULL);
    4980              : 
    4981              :     /*
    4982              :      * Revert to TopMemoryContext, to ensure we exit in a well-defined state
    4983              :      * whether there were any transactions to close or not.  (Callers that
    4984              :      * don't intend to exit soon should switch to some other context to avoid
    4985              :      * long-term memory leaks.)
    4986              :      */
    4987        19787 :     MemoryContextSwitchTo(TopMemoryContext);
    4988        19787 : }
    4989              : 
    4990              : /*
    4991              :  * IsTransactionBlock --- are we within a transaction block?
    4992              :  */
    4993              : bool
    4994       337618 : IsTransactionBlock(void)
    4995              : {
    4996       337618 :     TransactionState s = CurrentTransactionState;
    4997              : 
    4998       337618 :     if (s->blockState == TBLOCK_DEFAULT || s->blockState == TBLOCK_STARTED)
    4999       270552 :         return false;
    5000              : 
    5001        67066 :     return true;
    5002              : }
    5003              : 
    5004              : /*
    5005              :  * IsTransactionOrTransactionBlock --- are we within either a transaction
    5006              :  * or a transaction block?  (The backend is only really "idle" when this
    5007              :  * returns false.)
    5008              :  *
    5009              :  * This should match up with IsTransactionBlock and IsTransactionState.
    5010              :  */
    5011              : bool
    5012       454715 : IsTransactionOrTransactionBlock(void)
    5013              : {
    5014       454715 :     TransactionState s = CurrentTransactionState;
    5015              : 
    5016       454715 :     if (s->blockState == TBLOCK_DEFAULT)
    5017       358281 :         return false;
    5018              : 
    5019        96434 :     return true;
    5020              : }
    5021              : 
    5022              : /*
    5023              :  * TransactionBlockStatusCode - return status code to send in ReadyForQuery
    5024              :  */
    5025              : char
    5026       416488 : TransactionBlockStatusCode(void)
    5027              : {
    5028       416488 :     TransactionState s = CurrentTransactionState;
    5029              : 
    5030       416488 :     switch (s->blockState)
    5031              :     {
    5032       320747 :         case TBLOCK_DEFAULT:
    5033              :         case TBLOCK_STARTED:
    5034       320747 :             return 'I';         /* idle --- not in transaction */
    5035        94602 :         case TBLOCK_BEGIN:
    5036              :         case TBLOCK_SUBBEGIN:
    5037              :         case TBLOCK_INPROGRESS:
    5038              :         case TBLOCK_IMPLICIT_INPROGRESS:
    5039              :         case TBLOCK_PARALLEL_INPROGRESS:
    5040              :         case TBLOCK_SUBINPROGRESS:
    5041              :         case TBLOCK_END:
    5042              :         case TBLOCK_SUBRELEASE:
    5043              :         case TBLOCK_SUBCOMMIT:
    5044              :         case TBLOCK_PREPARE:
    5045        94602 :             return 'T';         /* in transaction */
    5046         1139 :         case TBLOCK_ABORT:
    5047              :         case TBLOCK_SUBABORT:
    5048              :         case TBLOCK_ABORT_END:
    5049              :         case TBLOCK_SUBABORT_END:
    5050              :         case TBLOCK_ABORT_PENDING:
    5051              :         case TBLOCK_SUBABORT_PENDING:
    5052              :         case TBLOCK_SUBRESTART:
    5053              :         case TBLOCK_SUBABORT_RESTART:
    5054         1139 :             return 'E';         /* in failed transaction */
    5055              :     }
    5056              : 
    5057              :     /* should never get here */
    5058            0 :     elog(FATAL, "invalid transaction block state: %s",
    5059              :          BlockStateAsString(s->blockState));
    5060              :     return 0;                   /* keep compiler quiet */
    5061              : }
    5062              : 
    5063              : /*
    5064              :  * IsSubTransaction
    5065              :  */
    5066              : bool
    5067       664330 : IsSubTransaction(void)
    5068              : {
    5069       664330 :     TransactionState s = CurrentTransactionState;
    5070              : 
    5071       664330 :     if (s->nestingLevel >= 2)
    5072          248 :         return true;
    5073              : 
    5074       664082 :     return false;
    5075              : }
    5076              : 
    5077              : /*
    5078              :  * StartSubTransaction
    5079              :  *
    5080              :  * If you're wondering why this is separate from PushTransaction: it's because
    5081              :  * we can't conveniently do this stuff right inside DefineSavepoint.  The
    5082              :  * SAVEPOINT utility command will be executed inside a Portal, and if we
    5083              :  * muck with CurrentMemoryContext or CurrentResourceOwner then exit from
    5084              :  * the Portal will undo those settings.  So we make DefineSavepoint just
    5085              :  * push a dummy transaction block, and when control returns to the main
    5086              :  * idle loop, CommitTransactionCommand will be called, and we'll come here
    5087              :  * to finish starting the subtransaction.
    5088              :  */
    5089              : static void
    5090        11797 : StartSubTransaction(void)
    5091              : {
    5092        11797 :     TransactionState s = CurrentTransactionState;
    5093              : 
    5094        11797 :     if (s->state != TRANS_DEFAULT)
    5095            0 :         elog(WARNING, "StartSubTransaction while in %s state",
    5096              :              TransStateAsString(s->state));
    5097              : 
    5098        11797 :     s->state = TRANS_START;
    5099              : 
    5100              :     /*
    5101              :      * Initialize subsystems for new subtransaction
    5102              :      *
    5103              :      * must initialize resource-management stuff first
    5104              :      */
    5105        11797 :     AtSubStart_Memory();
    5106        11797 :     AtSubStart_ResourceOwner();
    5107        11797 :     AfterTriggerBeginSubXact();
    5108              : 
    5109        11797 :     s->state = TRANS_INPROGRESS;
    5110              : 
    5111              :     /*
    5112              :      * Call start-of-subxact callbacks
    5113              :      */
    5114        11797 :     CallSubXactCallbacks(SUBXACT_EVENT_START_SUB, s->subTransactionId,
    5115        11797 :                          s->parent->subTransactionId);
    5116              : 
    5117        11797 :     ShowTransactionState("StartSubTransaction");
    5118        11797 : }
    5119              : 
    5120              : /*
    5121              :  * CommitSubTransaction
    5122              :  *
    5123              :  *  The caller has to make sure to always reassign CurrentTransactionState
    5124              :  *  if it has a local pointer to it after calling this function.
    5125              :  */
    5126              : static void
    5127         5855 : CommitSubTransaction(void)
    5128              : {
    5129         5855 :     TransactionState s = CurrentTransactionState;
    5130              : 
    5131         5855 :     ShowTransactionState("CommitSubTransaction");
    5132              : 
    5133         5855 :     if (s->state != TRANS_INPROGRESS)
    5134            0 :         elog(WARNING, "CommitSubTransaction while in %s state",
    5135              :              TransStateAsString(s->state));
    5136              : 
    5137              :     /* Pre-commit processing goes here */
    5138              : 
    5139         5855 :     CallSubXactCallbacks(SUBXACT_EVENT_PRE_COMMIT_SUB, s->subTransactionId,
    5140         5855 :                          s->parent->subTransactionId);
    5141              : 
    5142              :     /*
    5143              :      * If this subxact has started any unfinished parallel operation, clean up
    5144              :      * its workers and exit parallel mode.  Warn about leaked resources.
    5145              :      */
    5146         5855 :     AtEOSubXact_Parallel(true, s->subTransactionId);
    5147         5855 :     if (s->parallelModeLevel != 0)
    5148              :     {
    5149            0 :         elog(WARNING, "parallelModeLevel is %d not 0 at end of subtransaction",
    5150              :              s->parallelModeLevel);
    5151            0 :         s->parallelModeLevel = 0;
    5152              :     }
    5153              : 
    5154              :     /* Do the actual "commit", such as it is */
    5155         5855 :     s->state = TRANS_COMMIT;
    5156              : 
    5157              :     /* Must CCI to ensure commands of subtransaction are seen as done */
    5158         5855 :     CommandCounterIncrement();
    5159              : 
    5160              :     /*
    5161              :      * Prior to 8.4 we marked subcommit in clog at this point.  We now only
    5162              :      * perform that step, if required, as part of the atomic update of the
    5163              :      * whole transaction tree at top level commit or abort.
    5164              :      */
    5165              : 
    5166              :     /* Post-commit cleanup */
    5167         5855 :     if (FullTransactionIdIsValid(s->fullTransactionId))
    5168         3731 :         AtSubCommit_childXids();
    5169         5855 :     AfterTriggerEndSubXact(true);
    5170         5855 :     AtSubCommit_Portals(s->subTransactionId,
    5171         5855 :                         s->parent->subTransactionId,
    5172         5855 :                         s->parent->nestingLevel,
    5173         5855 :                         s->parent->curTransactionOwner);
    5174         5855 :     AtEOSubXact_LargeObject(true, s->subTransactionId,
    5175         5855 :                             s->parent->subTransactionId);
    5176         5855 :     AtSubCommit_Notify();
    5177              : 
    5178         5855 :     CallSubXactCallbacks(SUBXACT_EVENT_COMMIT_SUB, s->subTransactionId,
    5179         5855 :                          s->parent->subTransactionId);
    5180              : 
    5181         5855 :     ResourceOwnerRelease(s->curTransactionOwner,
    5182              :                          RESOURCE_RELEASE_BEFORE_LOCKS,
    5183              :                          true, false);
    5184         5855 :     AtEOSubXact_RelationCache(true, s->subTransactionId,
    5185         5855 :                               s->parent->subTransactionId);
    5186         5855 :     AtEOSubXact_TypeCache();
    5187         5855 :     AtEOSubXact_Inval(true);
    5188         5855 :     AtSubCommit_smgr();
    5189              : 
    5190              :     /*
    5191              :      * The only lock we actually release here is the subtransaction XID lock.
    5192              :      */
    5193         5855 :     CurrentResourceOwner = s->curTransactionOwner;
    5194         5855 :     if (FullTransactionIdIsValid(s->fullTransactionId))
    5195         3731 :         XactLockTableDelete(XidFromFullTransactionId(s->fullTransactionId));
    5196              : 
    5197              :     /*
    5198              :      * Other locks should get transferred to their parent resource owner.
    5199              :      */
    5200         5855 :     ResourceOwnerRelease(s->curTransactionOwner,
    5201              :                          RESOURCE_RELEASE_LOCKS,
    5202              :                          true, false);
    5203         5855 :     ResourceOwnerRelease(s->curTransactionOwner,
    5204              :                          RESOURCE_RELEASE_AFTER_LOCKS,
    5205              :                          true, false);
    5206              : 
    5207         5855 :     AtEOXact_GUC(true, s->gucNestLevel);
    5208         5855 :     AtEOSubXact_SPI(true, s->subTransactionId);
    5209         5855 :     AtEOSubXact_on_commit_actions(true, s->subTransactionId,
    5210         5855 :                                   s->parent->subTransactionId);
    5211         5855 :     AtEOSubXact_Namespace(true, s->subTransactionId,
    5212         5855 :                           s->parent->subTransactionId);
    5213         5855 :     AtEOSubXact_Files(true, s->subTransactionId,
    5214         5855 :                       s->parent->subTransactionId);
    5215         5855 :     AtEOSubXact_HashTables(true, s->nestingLevel);
    5216         5855 :     AtEOSubXact_PgStat(true, s->nestingLevel);
    5217         5855 :     AtSubCommit_Snapshot(s->nestingLevel);
    5218              : 
    5219              :     /*
    5220              :      * We need to restore the upper transaction's read-only state, in case the
    5221              :      * upper is read-write while the child is read-only; GUC will incorrectly
    5222              :      * think it should leave the child state in place.
    5223              :      */
    5224         5855 :     XactReadOnly = s->prevXactReadOnly;
    5225              : 
    5226         5855 :     CurrentResourceOwner = s->parent->curTransactionOwner;
    5227         5855 :     CurTransactionResourceOwner = s->parent->curTransactionOwner;
    5228         5855 :     ResourceOwnerDelete(s->curTransactionOwner);
    5229         5855 :     s->curTransactionOwner = NULL;
    5230              : 
    5231         5855 :     AtSubCommit_Memory();
    5232              : 
    5233         5855 :     s->state = TRANS_DEFAULT;
    5234              : 
    5235         5855 :     PopTransaction();
    5236         5855 : }
    5237              : 
    5238              : /*
    5239              :  * AbortSubTransaction
    5240              :  */
    5241              : static void
    5242         5942 : AbortSubTransaction(void)
    5243              : {
    5244         5942 :     TransactionState s = CurrentTransactionState;
    5245              : 
    5246              :     /* Prevent cancel/die interrupt while cleaning up */
    5247         5942 :     HOLD_INTERRUPTS();
    5248              : 
    5249              :     /* Make sure we have a valid memory context and resource owner */
    5250         5942 :     AtSubAbort_Memory();
    5251         5942 :     AtSubAbort_ResourceOwner();
    5252              : 
    5253              :     /*
    5254              :      * Release any LW locks we might be holding as quickly as possible.
    5255              :      * (Regular locks, however, must be held till we finish aborting.)
    5256              :      * Releasing LW locks is critical since we might try to grab them again
    5257              :      * while cleaning up!
    5258              :      *
    5259              :      * FIXME This may be incorrect --- Are there some locks we should keep?
    5260              :      * Buffer locks, for example?  I don't think so but I'm not sure.
    5261              :      */
    5262         5942 :     LWLockReleaseAll();
    5263              : 
    5264         5942 :     pgstat_report_wait_end();
    5265         5942 :     pgstat_progress_end_command();
    5266              : 
    5267         5942 :     pgaio_error_cleanup();
    5268              : 
    5269         5942 :     UnlockBuffers();
    5270              : 
    5271              :     /* Reset WAL record construction state */
    5272         5942 :     XLogResetInsertion();
    5273              : 
    5274              :     /* Cancel condition variable sleep */
    5275         5942 :     ConditionVariableCancelSleep();
    5276              : 
    5277              :     /*
    5278              :      * Also clean up any open wait for lock, since the lock manager will choke
    5279              :      * if we try to wait for another lock before doing this.
    5280              :      */
    5281         5942 :     LockErrorCleanup();
    5282              : 
    5283              :     /*
    5284              :      * If any timeout events are still active, make sure the timeout interrupt
    5285              :      * is scheduled.  This covers possible loss of a timeout interrupt due to
    5286              :      * longjmp'ing out of the SIGINT handler (see notes in handle_sig_alarm).
    5287              :      * We delay this till after LockErrorCleanup so that we don't uselessly
    5288              :      * reschedule lock or deadlock check timeouts.
    5289              :      */
    5290         5942 :     reschedule_timeouts();
    5291              : 
    5292              :     /*
    5293              :      * Re-enable signals, in case we got here by longjmp'ing out of a signal
    5294              :      * handler.  We do this fairly early in the sequence so that the timeout
    5295              :      * infrastructure will be functional if needed while aborting.
    5296              :      */
    5297         5942 :     sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
    5298              : 
    5299              :     /*
    5300              :      * check the current transaction state
    5301              :      */
    5302         5942 :     ShowTransactionState("AbortSubTransaction");
    5303              : 
    5304         5942 :     if (s->state != TRANS_INPROGRESS)
    5305            0 :         elog(WARNING, "AbortSubTransaction while in %s state",
    5306              :              TransStateAsString(s->state));
    5307              : 
    5308         5942 :     s->state = TRANS_ABORT;
    5309              : 
    5310              :     /*
    5311              :      * Reset user ID which might have been changed transiently.  (See notes in
    5312              :      * AbortTransaction.)
    5313              :      */
    5314         5942 :     SetUserIdAndSecContext(s->prevUser, s->prevSecContext);
    5315              : 
    5316              :     /* Forget about any active REINDEX. */
    5317         5942 :     ResetReindexState(s->nestingLevel);
    5318              : 
    5319              :     /* Reset logical streaming state. */
    5320         5942 :     ResetLogicalStreamingState();
    5321              : 
    5322              :     /*
    5323              :      * No need for SnapBuildResetExportedSnapshotState() here, snapshot
    5324              :      * exports are not supported in subtransactions.
    5325              :      */
    5326              : 
    5327              :     /*
    5328              :      * If this subxact has started any unfinished parallel operation, clean up
    5329              :      * its workers and exit parallel mode.  Don't warn about leaked resources.
    5330              :      */
    5331         5942 :     AtEOSubXact_Parallel(false, s->subTransactionId);
    5332         5942 :     s->parallelModeLevel = 0;
    5333              : 
    5334              :     /*
    5335              :      * We can skip all this stuff if the subxact failed before creating a
    5336              :      * ResourceOwner...
    5337              :      */
    5338         5942 :     if (s->curTransactionOwner)
    5339              :     {
    5340         5942 :         AfterTriggerEndSubXact(false);
    5341         5942 :         AtSubAbort_Portals(s->subTransactionId,
    5342         5942 :                            s->parent->subTransactionId,
    5343              :                            s->curTransactionOwner,
    5344         5942 :                            s->parent->curTransactionOwner);
    5345         5942 :         AtEOSubXact_LargeObject(false, s->subTransactionId,
    5346         5942 :                                 s->parent->subTransactionId);
    5347         5942 :         AtSubAbort_Notify();
    5348              : 
    5349              :         /* Advertise the fact that we aborted in pg_xact. */
    5350         5942 :         (void) RecordTransactionAbort(true);
    5351              : 
    5352              :         /* Post-abort cleanup */
    5353         5942 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5354          846 :             AtSubAbort_childXids();
    5355              : 
    5356         5942 :         CallSubXactCallbacks(SUBXACT_EVENT_ABORT_SUB, s->subTransactionId,
    5357         5942 :                              s->parent->subTransactionId);
    5358              : 
    5359         5942 :         ResourceOwnerRelease(s->curTransactionOwner,
    5360              :                              RESOURCE_RELEASE_BEFORE_LOCKS,
    5361              :                              false, false);
    5362              : 
    5363         5942 :         AtEOXact_Aio(false);
    5364         5942 :         AtEOSubXact_RelationCache(false, s->subTransactionId,
    5365         5942 :                                   s->parent->subTransactionId);
    5366         5942 :         AtEOSubXact_TypeCache();
    5367         5942 :         AtEOSubXact_Inval(false);
    5368         5942 :         ResourceOwnerRelease(s->curTransactionOwner,
    5369              :                              RESOURCE_RELEASE_LOCKS,
    5370              :                              false, false);
    5371         5942 :         ResourceOwnerRelease(s->curTransactionOwner,
    5372              :                              RESOURCE_RELEASE_AFTER_LOCKS,
    5373              :                              false, false);
    5374         5942 :         AtSubAbort_smgr();
    5375              : 
    5376         5942 :         AtEOXact_GUC(false, s->gucNestLevel);
    5377         5942 :         AtEOSubXact_SPI(false, s->subTransactionId);
    5378         5942 :         AtEOSubXact_on_commit_actions(false, s->subTransactionId,
    5379         5942 :                                       s->parent->subTransactionId);
    5380         5942 :         AtEOSubXact_Namespace(false, s->subTransactionId,
    5381         5942 :                               s->parent->subTransactionId);
    5382         5942 :         AtEOSubXact_Files(false, s->subTransactionId,
    5383         5942 :                           s->parent->subTransactionId);
    5384         5942 :         AtEOSubXact_HashTables(false, s->nestingLevel);
    5385         5942 :         AtEOSubXact_PgStat(false, s->nestingLevel);
    5386         5942 :         AtSubAbort_Snapshot(s->nestingLevel);
    5387              :     }
    5388              : 
    5389              :     /*
    5390              :      * Restore the upper transaction's read-only state, too.  This should be
    5391              :      * redundant with GUC's cleanup but we may as well do it for consistency
    5392              :      * with the commit case.
    5393              :      */
    5394         5942 :     XactReadOnly = s->prevXactReadOnly;
    5395              : 
    5396         5942 :     RESUME_INTERRUPTS();
    5397         5942 : }
    5398              : 
    5399              : /*
    5400              :  * CleanupSubTransaction
    5401              :  *
    5402              :  *  The caller has to make sure to always reassign CurrentTransactionState
    5403              :  *  if it has a local pointer to it after calling this function.
    5404              :  */
    5405              : static void
    5406         5942 : CleanupSubTransaction(void)
    5407              : {
    5408         5942 :     TransactionState s = CurrentTransactionState;
    5409              : 
    5410         5942 :     ShowTransactionState("CleanupSubTransaction");
    5411              : 
    5412         5942 :     if (s->state != TRANS_ABORT)
    5413            0 :         elog(WARNING, "CleanupSubTransaction while in %s state",
    5414              :              TransStateAsString(s->state));
    5415              : 
    5416         5942 :     AtSubCleanup_Portals(s->subTransactionId);
    5417              : 
    5418         5942 :     CurrentResourceOwner = s->parent->curTransactionOwner;
    5419         5942 :     CurTransactionResourceOwner = s->parent->curTransactionOwner;
    5420         5942 :     if (s->curTransactionOwner)
    5421         5942 :         ResourceOwnerDelete(s->curTransactionOwner);
    5422         5942 :     s->curTransactionOwner = NULL;
    5423              : 
    5424         5942 :     AtSubCleanup_Memory();
    5425              : 
    5426         5942 :     s->state = TRANS_DEFAULT;
    5427              : 
    5428         5942 :     PopTransaction();
    5429         5942 : }
    5430              : 
    5431              : /*
    5432              :  * PushTransaction
    5433              :  *      Create transaction state stack entry for a subtransaction
    5434              :  *
    5435              :  *  The caller has to make sure to always reassign CurrentTransactionState
    5436              :  *  if it has a local pointer to it after calling this function.
    5437              :  */
    5438              : static void
    5439        11797 : PushTransaction(void)
    5440              : {
    5441        11797 :     TransactionState p = CurrentTransactionState;
    5442              :     TransactionState s;
    5443              : 
    5444              :     /*
    5445              :      * We keep subtransaction state nodes in TopTransactionContext.
    5446              :      */
    5447              :     s = (TransactionState)
    5448        11797 :         MemoryContextAllocZero(TopTransactionContext,
    5449              :                                sizeof(TransactionStateData));
    5450              : 
    5451              :     /*
    5452              :      * Assign a subtransaction ID, watching out for counter wraparound.
    5453              :      */
    5454        11797 :     currentSubTransactionId += 1;
    5455        11797 :     if (currentSubTransactionId == InvalidSubTransactionId)
    5456              :     {
    5457            0 :         currentSubTransactionId -= 1;
    5458            0 :         pfree(s);
    5459            0 :         ereport(ERROR,
    5460              :                 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
    5461              :                  errmsg("cannot have more than 2^32-1 subtransactions in a transaction")));
    5462              :     }
    5463              : 
    5464              :     /*
    5465              :      * We can now stack a minimally valid subtransaction without fear of
    5466              :      * failure.
    5467              :      */
    5468        11797 :     s->fullTransactionId = InvalidFullTransactionId; /* until assigned */
    5469        11797 :     s->subTransactionId = currentSubTransactionId;
    5470        11797 :     s->parent = p;
    5471        11797 :     s->nestingLevel = p->nestingLevel + 1;
    5472        11797 :     s->gucNestLevel = NewGUCNestLevel();
    5473        11797 :     s->savepointLevel = p->savepointLevel;
    5474        11797 :     s->state = TRANS_DEFAULT;
    5475        11797 :     s->blockState = TBLOCK_SUBBEGIN;
    5476        11797 :     GetUserIdAndSecContext(&s->prevUser, &s->prevSecContext);
    5477        11797 :     s->prevXactReadOnly = XactReadOnly;
    5478        11797 :     s->startedInRecovery = p->startedInRecovery;
    5479        11797 :     s->parallelModeLevel = 0;
    5480        11797 :     s->parallelChildXact = (p->parallelModeLevel != 0 || p->parallelChildXact);
    5481        11797 :     s->topXidLogged = false;
    5482              : 
    5483        11797 :     CurrentTransactionState = s;
    5484              : 
    5485              :     /*
    5486              :      * AbortSubTransaction and CleanupSubTransaction have to be able to cope
    5487              :      * with the subtransaction from here on out; in particular they should not
    5488              :      * assume that it necessarily has a transaction context, resource owner,
    5489              :      * or XID.
    5490              :      */
    5491        11797 : }
    5492              : 
    5493              : /*
    5494              :  * PopTransaction
    5495              :  *      Pop back to parent transaction state
    5496              :  *
    5497              :  *  The caller has to make sure to always reassign CurrentTransactionState
    5498              :  *  if it has a local pointer to it after calling this function.
    5499              :  */
    5500              : static void
    5501        11797 : PopTransaction(void)
    5502              : {
    5503        11797 :     TransactionState s = CurrentTransactionState;
    5504              : 
    5505        11797 :     if (s->state != TRANS_DEFAULT)
    5506            0 :         elog(WARNING, "PopTransaction while in %s state",
    5507              :              TransStateAsString(s->state));
    5508              : 
    5509        11797 :     if (s->parent == NULL)
    5510            0 :         elog(FATAL, "PopTransaction with no parent");
    5511              : 
    5512        11797 :     CurrentTransactionState = s->parent;
    5513              : 
    5514              :     /* Let's just make sure CurTransactionContext is good */
    5515        11797 :     CurTransactionContext = s->parent->curTransactionContext;
    5516        11797 :     MemoryContextSwitchTo(CurTransactionContext);
    5517              : 
    5518              :     /* Ditto for ResourceOwner links */
    5519        11797 :     CurTransactionResourceOwner = s->parent->curTransactionOwner;
    5520        11797 :     CurrentResourceOwner = s->parent->curTransactionOwner;
    5521              : 
    5522              :     /* Free the old child structure */
    5523        11797 :     if (s->name)
    5524         2083 :         pfree(s->name);
    5525        11797 :     pfree(s);
    5526        11797 : }
    5527              : 
    5528              : /*
    5529              :  * EstimateTransactionStateSpace
    5530              :  *      Estimate the amount of space that will be needed by
    5531              :  *      SerializeTransactionState.  It would be OK to overestimate slightly,
    5532              :  *      but it's simple for us to work out the precise value, so we do.
    5533              :  */
    5534              : Size
    5535          672 : EstimateTransactionStateSpace(void)
    5536              : {
    5537              :     TransactionState s;
    5538          672 :     Size        nxids = 0;
    5539          672 :     Size        size = SerializedTransactionStateHeaderSize;
    5540              : 
    5541         3036 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    5542              :     {
    5543         2364 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5544         1359 :             nxids = add_size(nxids, 1);
    5545         2364 :         nxids = add_size(nxids, s->nChildXids);
    5546              :     }
    5547              : 
    5548          672 :     return add_size(size, mul_size(sizeof(TransactionId), nxids));
    5549              : }
    5550              : 
    5551              : /*
    5552              :  * SerializeTransactionState
    5553              :  *      Write out relevant details of our transaction state that will be
    5554              :  *      needed by a parallel worker.
    5555              :  *
    5556              :  * We need to save and restore XactDeferrable, XactIsoLevel, and the XIDs
    5557              :  * associated with this transaction.  These are serialized into a
    5558              :  * caller-supplied buffer big enough to hold the number of bytes reported by
    5559              :  * EstimateTransactionStateSpace().  We emit the XIDs in sorted order for the
    5560              :  * convenience of the receiving process.
    5561              :  */
    5562              : void
    5563          672 : SerializeTransactionState(Size maxsize, char *start_address)
    5564              : {
    5565              :     TransactionState s;
    5566          672 :     Size        nxids = 0;
    5567          672 :     Size        i = 0;
    5568              :     TransactionId *workspace;
    5569              :     SerializedTransactionState *result;
    5570              : 
    5571          672 :     result = (SerializedTransactionState *) start_address;
    5572              : 
    5573          672 :     result->xactIsoLevel = XactIsoLevel;
    5574          672 :     result->xactDeferrable = XactDeferrable;
    5575          672 :     result->topFullTransactionId = XactTopFullTransactionId;
    5576          672 :     result->currentFullTransactionId =
    5577          672 :         CurrentTransactionState->fullTransactionId;
    5578          672 :     result->currentCommandId = currentCommandId;
    5579              : 
    5580              :     /*
    5581              :      * If we're running in a parallel worker and launching a parallel worker
    5582              :      * of our own, we can just pass along the information that was passed to
    5583              :      * us.
    5584              :      */
    5585          672 :     if (nParallelCurrentXids > 0)
    5586              :     {
    5587            0 :         result->nParallelCurrentXids = nParallelCurrentXids;
    5588            0 :         memcpy(&result->parallelCurrentXids[0], ParallelCurrentXids,
    5589              :                nParallelCurrentXids * sizeof(TransactionId));
    5590            0 :         return;
    5591              :     }
    5592              : 
    5593              :     /*
    5594              :      * OK, we need to generate a sorted list of XIDs that our workers should
    5595              :      * view as current.  First, figure out how many there are.
    5596              :      */
    5597         3036 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    5598              :     {
    5599         2364 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5600         1359 :             nxids = add_size(nxids, 1);
    5601         2364 :         nxids = add_size(nxids, s->nChildXids);
    5602              :     }
    5603              :     Assert(SerializedTransactionStateHeaderSize + nxids * sizeof(TransactionId)
    5604              :            <= maxsize);
    5605              : 
    5606              :     /* Copy them to our scratch space. */
    5607          672 :     workspace = palloc(nxids * sizeof(TransactionId));
    5608         3036 :     for (s = CurrentTransactionState; s != NULL; s = s->parent)
    5609              :     {
    5610         2364 :         if (FullTransactionIdIsValid(s->fullTransactionId))
    5611         1359 :             workspace[i++] = XidFromFullTransactionId(s->fullTransactionId);
    5612         2364 :         if (s->nChildXids > 0)
    5613            0 :             memcpy(&workspace[i], s->childXids,
    5614            0 :                    s->nChildXids * sizeof(TransactionId));
    5615         2364 :         i += s->nChildXids;
    5616              :     }
    5617              :     Assert(i == nxids);
    5618              : 
    5619              :     /* Sort them. */
    5620          672 :     qsort(workspace, nxids, sizeof(TransactionId), xidComparator);
    5621              : 
    5622              :     /* Copy data into output area. */
    5623          672 :     result->nParallelCurrentXids = nxids;
    5624          672 :     memcpy(&result->parallelCurrentXids[0], workspace,
    5625              :            nxids * sizeof(TransactionId));
    5626              : }
    5627              : 
    5628              : /*
    5629              :  * StartParallelWorkerTransaction
    5630              :  *      Start a parallel worker transaction, restoring the relevant
    5631              :  *      transaction state serialized by SerializeTransactionState.
    5632              :  */
    5633              : void
    5634         1999 : StartParallelWorkerTransaction(char *tstatespace)
    5635              : {
    5636              :     SerializedTransactionState *tstate;
    5637              : 
    5638              :     Assert(CurrentTransactionState->blockState == TBLOCK_DEFAULT);
    5639         1999 :     StartTransaction();
    5640              : 
    5641         1999 :     tstate = (SerializedTransactionState *) tstatespace;
    5642         1999 :     XactIsoLevel = tstate->xactIsoLevel;
    5643         1999 :     XactDeferrable = tstate->xactDeferrable;
    5644         1999 :     XactTopFullTransactionId = tstate->topFullTransactionId;
    5645         1999 :     CurrentTransactionState->fullTransactionId =
    5646              :         tstate->currentFullTransactionId;
    5647         1999 :     currentCommandId = tstate->currentCommandId;
    5648         1999 :     nParallelCurrentXids = tstate->nParallelCurrentXids;
    5649         1999 :     ParallelCurrentXids = &tstate->parallelCurrentXids[0];
    5650              : 
    5651         1999 :     CurrentTransactionState->blockState = TBLOCK_PARALLEL_INPROGRESS;
    5652         1999 : }
    5653              : 
    5654              : /*
    5655              :  * EndParallelWorkerTransaction
    5656              :  *      End a parallel worker transaction.
    5657              :  */
    5658              : void
    5659         1991 : EndParallelWorkerTransaction(void)
    5660              : {
    5661              :     Assert(CurrentTransactionState->blockState == TBLOCK_PARALLEL_INPROGRESS);
    5662         1991 :     CommitTransaction();
    5663         1991 :     CurrentTransactionState->blockState = TBLOCK_DEFAULT;
    5664         1991 : }
    5665              : 
    5666              : /*
    5667              :  * ShowTransactionState
    5668              :  *      Debug support
    5669              :  */
    5670              : static void
    5671      1225024 : ShowTransactionState(const char *str)
    5672              : {
    5673              :     /* skip work if message will definitely not be printed */
    5674      1225024 :     if (message_level_is_interesting(DEBUG5))
    5675            0 :         ShowTransactionStateRec(str, CurrentTransactionState);
    5676      1225024 : }
    5677              : 
    5678              : /*
    5679              :  * ShowTransactionStateRec
    5680              :  *      Recursive subroutine for ShowTransactionState
    5681              :  */
    5682              : static void
    5683            0 : ShowTransactionStateRec(const char *str, TransactionState s)
    5684              : {
    5685              :     StringInfoData buf;
    5686              : 
    5687            0 :     if (s->parent)
    5688              :     {
    5689              :         /*
    5690              :          * Since this function recurses, it could be driven to stack overflow.
    5691              :          * This is just a debugging aid, so we can leave out some details
    5692              :          * instead of erroring out with check_stack_depth().
    5693              :          */
    5694            0 :         if (stack_is_too_deep())
    5695            0 :             ereport(DEBUG5,
    5696              :                     (errmsg_internal("%s(%d): parent omitted to avoid stack overflow",
    5697              :                                      str, s->nestingLevel)));
    5698              :         else
    5699            0 :             ShowTransactionStateRec(str, s->parent);
    5700              :     }
    5701              : 
    5702            0 :     initStringInfo(&buf);
    5703            0 :     if (s->nChildXids > 0)
    5704              :     {
    5705              :         int         i;
    5706              : 
    5707            0 :         appendStringInfo(&buf, ", children: %u", s->childXids[0]);
    5708            0 :         for (i = 1; i < s->nChildXids; i++)
    5709            0 :             appendStringInfo(&buf, " %u", s->childXids[i]);
    5710              :     }
    5711            0 :     ereport(DEBUG5,
    5712              :             (errmsg_internal("%s(%d) name: %s; blockState: %s; state: %s, xid/subid/cid: %u/%u/%u%s%s",
    5713              :                              str, s->nestingLevel,
    5714              :                              s->name ? s->name : "unnamed",
    5715              :                              BlockStateAsString(s->blockState),
    5716              :                              TransStateAsString(s->state),
    5717              :                              XidFromFullTransactionId(s->fullTransactionId),
    5718              :                              s->subTransactionId,
    5719              :                              currentCommandId,
    5720              :                              currentCommandIdUsed ? " (used)" : "",
    5721              :                              buf.data)));
    5722            0 :     pfree(buf.data);
    5723            0 : }
    5724              : 
    5725              : /*
    5726              :  * BlockStateAsString
    5727              :  *      Debug support
    5728              :  */
    5729              : static const char *
    5730            0 : BlockStateAsString(TBlockState blockState)
    5731              : {
    5732            0 :     switch (blockState)
    5733              :     {
    5734            0 :         case TBLOCK_DEFAULT:
    5735            0 :             return "DEFAULT";
    5736            0 :         case TBLOCK_STARTED:
    5737            0 :             return "STARTED";
    5738            0 :         case TBLOCK_BEGIN:
    5739            0 :             return "BEGIN";
    5740            0 :         case TBLOCK_INPROGRESS:
    5741            0 :             return "INPROGRESS";
    5742            0 :         case TBLOCK_IMPLICIT_INPROGRESS:
    5743            0 :             return "IMPLICIT_INPROGRESS";
    5744            0 :         case TBLOCK_PARALLEL_INPROGRESS:
    5745            0 :             return "PARALLEL_INPROGRESS";
    5746            0 :         case TBLOCK_END:
    5747            0 :             return "END";
    5748            0 :         case TBLOCK_ABORT:
    5749            0 :             return "ABORT";
    5750            0 :         case TBLOCK_ABORT_END:
    5751            0 :             return "ABORT_END";
    5752            0 :         case TBLOCK_ABORT_PENDING:
    5753            0 :             return "ABORT_PENDING";
    5754            0 :         case TBLOCK_PREPARE:
    5755            0 :             return "PREPARE";
    5756            0 :         case TBLOCK_SUBBEGIN:
    5757            0 :             return "SUBBEGIN";
    5758            0 :         case TBLOCK_SUBINPROGRESS:
    5759            0 :             return "SUBINPROGRESS";
    5760            0 :         case TBLOCK_SUBRELEASE:
    5761            0 :             return "SUBRELEASE";
    5762            0 :         case TBLOCK_SUBCOMMIT:
    5763            0 :             return "SUBCOMMIT";
    5764            0 :         case TBLOCK_SUBABORT:
    5765            0 :             return "SUBABORT";
    5766            0 :         case TBLOCK_SUBABORT_END:
    5767            0 :             return "SUBABORT_END";
    5768            0 :         case TBLOCK_SUBABORT_PENDING:
    5769            0 :             return "SUBABORT_PENDING";
    5770            0 :         case TBLOCK_SUBRESTART:
    5771            0 :             return "SUBRESTART";
    5772            0 :         case TBLOCK_SUBABORT_RESTART:
    5773            0 :             return "SUBABORT_RESTART";
    5774              :     }
    5775            0 :     return "UNRECOGNIZED";
    5776              : }
    5777              : 
    5778              : /*
    5779              :  * TransStateAsString
    5780              :  *      Debug support
    5781              :  */
    5782              : static const char *
    5783            0 : TransStateAsString(TransState state)
    5784              : {
    5785            0 :     switch (state)
    5786              :     {
    5787            0 :         case TRANS_DEFAULT:
    5788            0 :             return "DEFAULT";
    5789            0 :         case TRANS_START:
    5790            0 :             return "START";
    5791            0 :         case TRANS_INPROGRESS:
    5792            0 :             return "INPROGRESS";
    5793            0 :         case TRANS_COMMIT:
    5794            0 :             return "COMMIT";
    5795            0 :         case TRANS_ABORT:
    5796            0 :             return "ABORT";
    5797            0 :         case TRANS_PREPARE:
    5798            0 :             return "PREPARE";
    5799              :     }
    5800            0 :     return "UNRECOGNIZED";
    5801              : }
    5802              : 
    5803              : /*
    5804              :  * xactGetCommittedChildren
    5805              :  *
    5806              :  * Gets the list of committed children of the current transaction.  The return
    5807              :  * value is the number of child transactions.  *ptr is set to point to an
    5808              :  * array of TransactionIds.  The array is allocated in TopTransactionContext;
    5809              :  * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
    5810              :  * If there are no subxacts, *ptr is set to NULL.
    5811              :  */
    5812              : int
    5813       586966 : xactGetCommittedChildren(TransactionId **ptr)
    5814              : {
    5815       586966 :     TransactionState s = CurrentTransactionState;
    5816              : 
    5817       586966 :     if (s->nChildXids == 0)
    5818       586332 :         *ptr = NULL;
    5819              :     else
    5820          634 :         *ptr = s->childXids;
    5821              : 
    5822       586966 :     return s->nChildXids;
    5823              : }
    5824              : 
    5825              : /*
    5826              :  *  XLOG support routines
    5827              :  */
    5828              : 
    5829              : 
    5830              : /*
    5831              :  * Log the commit record for a plain or twophase transaction commit.
    5832              :  *
    5833              :  * A 2pc commit will be emitted when twophase_xid is valid, a plain one
    5834              :  * otherwise.
    5835              :  */
    5836              : XLogRecPtr
    5837       151695 : XactLogCommitRecord(TimestampTz commit_time,
    5838              :                     int nsubxacts, TransactionId *subxacts,
    5839              :                     int nrels, RelFileLocator *rels,
    5840              :                     int ndroppedstats, xl_xact_stats_item *droppedstats,
    5841              :                     int nmsgs, SharedInvalidationMessage *msgs,
    5842              :                     bool relcacheInval,
    5843              :                     int xactflags, TransactionId twophase_xid,
    5844              :                     const char *twophase_gid)
    5845              : {
    5846              :     xl_xact_commit xlrec;
    5847              :     xl_xact_xinfo xl_xinfo;
    5848              :     xl_xact_dbinfo xl_dbinfo;
    5849              :     xl_xact_subxacts xl_subxacts;
    5850              :     xl_xact_relfilelocators xl_relfilelocators;
    5851              :     xl_xact_stats_items xl_dropped_stats;
    5852              :     xl_xact_invals xl_invals;
    5853              :     xl_xact_twophase xl_twophase;
    5854              :     xl_xact_origin xl_origin;
    5855              :     uint8       info;
    5856              : 
    5857              :     Assert(CritSectionCount > 0);
    5858              : 
    5859       151695 :     xl_xinfo.xinfo = 0;
    5860              : 
    5861              :     /* decide between a plain and 2pc commit */
    5862       151695 :     if (!TransactionIdIsValid(twophase_xid))
    5863       151421 :         info = XLOG_XACT_COMMIT;
    5864              :     else
    5865          274 :         info = XLOG_XACT_COMMIT_PREPARED;
    5866              : 
    5867              :     /* First figure out and collect all the information needed */
    5868              : 
    5869       151695 :     xlrec.xact_time = commit_time;
    5870              : 
    5871       151695 :     if (relcacheInval)
    5872         4114 :         xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE;
    5873       151695 :     if (forceSyncCommit)
    5874          556 :         xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT;
    5875       151695 :     if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
    5876        51295 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
    5877              : 
    5878              :     /*
    5879              :      * Check if the caller would like to ask standbys for immediate feedback
    5880              :      * once this commit is applied.
    5881              :      */
    5882       151695 :     if (synchronous_commit >= SYNCHRONOUS_COMMIT_REMOTE_APPLY)
    5883            2 :         xl_xinfo.xinfo |= XACT_COMPLETION_APPLY_FEEDBACK;
    5884              : 
    5885              :     /*
    5886              :      * Relcache invalidations requires information about the current database
    5887              :      * and so does logical decoding.
    5888              :      */
    5889       151695 :     if (nmsgs > 0 || XLogLogicalInfoActive())
    5890              :     {
    5891        91089 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
    5892        91089 :         xl_dbinfo.dbId = MyDatabaseId;
    5893        91089 :         xl_dbinfo.tsId = MyDatabaseTableSpace;
    5894              :     }
    5895              : 
    5896       151695 :     if (nsubxacts > 0)
    5897              :     {
    5898          530 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
    5899          530 :         xl_subxacts.nsubxacts = nsubxacts;
    5900              :     }
    5901              : 
    5902       151695 :     if (nrels > 0)
    5903              :     {
    5904        12145 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
    5905        12145 :         xl_relfilelocators.nrels = nrels;
    5906        12145 :         info |= XLR_SPECIAL_REL_UPDATE;
    5907              :     }
    5908              : 
    5909       151695 :     if (ndroppedstats > 0)
    5910              :     {
    5911        14409 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
    5912        14409 :         xl_dropped_stats.nitems = ndroppedstats;
    5913              :     }
    5914              : 
    5915       151695 :     if (nmsgs > 0)
    5916              :     {
    5917        90184 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_INVALS;
    5918        90184 :         xl_invals.nmsgs = nmsgs;
    5919              :     }
    5920              : 
    5921       151695 :     if (TransactionIdIsValid(twophase_xid))
    5922              :     {
    5923          274 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
    5924          274 :         xl_twophase.xid = twophase_xid;
    5925              :         Assert(twophase_gid != NULL);
    5926              : 
    5927          274 :         if (XLogLogicalInfoActive())
    5928           41 :             xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
    5929              :     }
    5930              : 
    5931              :     /* dump transaction origin information */
    5932       151695 :     if (replorigin_xact_state.origin != InvalidReplOriginId)
    5933              :     {
    5934         1097 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
    5935              : 
    5936         1097 :         xl_origin.origin_lsn = replorigin_xact_state.origin_lsn;
    5937         1097 :         xl_origin.origin_timestamp = replorigin_xact_state.origin_timestamp;
    5938              :     }
    5939              : 
    5940       151695 :     if (xl_xinfo.xinfo != 0)
    5941        97164 :         info |= XLOG_XACT_HAS_INFO;
    5942              : 
    5943              :     /* Then include all the collected data into the commit record. */
    5944              : 
    5945       151695 :     XLogBeginInsert();
    5946              : 
    5947       151695 :     XLogRegisterData(&xlrec, sizeof(xl_xact_commit));
    5948              : 
    5949       151695 :     if (xl_xinfo.xinfo != 0)
    5950        97164 :         XLogRegisterData(&xl_xinfo.xinfo, sizeof(xl_xinfo.xinfo));
    5951              : 
    5952       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
    5953        91089 :         XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo));
    5954              : 
    5955       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
    5956              :     {
    5957          530 :         XLogRegisterData(&xl_subxacts,
    5958              :                          MinSizeOfXactSubxacts);
    5959          530 :         XLogRegisterData(subxacts,
    5960              :                          nsubxacts * sizeof(TransactionId));
    5961              :     }
    5962              : 
    5963       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
    5964              :     {
    5965        12145 :         XLogRegisterData(&xl_relfilelocators,
    5966              :                          MinSizeOfXactRelfileLocators);
    5967        12145 :         XLogRegisterData(rels,
    5968              :                          nrels * sizeof(RelFileLocator));
    5969              :     }
    5970              : 
    5971       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
    5972              :     {
    5973        14409 :         XLogRegisterData(&xl_dropped_stats,
    5974              :                          MinSizeOfXactStatsItems);
    5975        14409 :         XLogRegisterData(droppedstats,
    5976              :                          ndroppedstats * sizeof(xl_xact_stats_item));
    5977              :     }
    5978              : 
    5979       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_INVALS)
    5980              :     {
    5981        90184 :         XLogRegisterData(&xl_invals, MinSizeOfXactInvals);
    5982        90184 :         XLogRegisterData(msgs,
    5983              :                          nmsgs * sizeof(SharedInvalidationMessage));
    5984              :     }
    5985              : 
    5986       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
    5987              :     {
    5988          274 :         XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase));
    5989          274 :         if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
    5990           41 :             XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1);
    5991              :     }
    5992              : 
    5993       151695 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
    5994         1097 :         XLogRegisterData(&xl_origin, sizeof(xl_xact_origin));
    5995              : 
    5996              :     /* we allow filtering by xacts */
    5997       151695 :     XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
    5998              : 
    5999       151695 :     return XLogInsert(RM_XACT_ID, info);
    6000              : }
    6001              : 
    6002              : /*
    6003              :  * Log the commit record for a plain or twophase transaction abort.
    6004              :  *
    6005              :  * A 2pc abort will be emitted when twophase_xid is valid, a plain one
    6006              :  * otherwise.
    6007              :  */
    6008              : XLogRecPtr
    6009         8678 : XactLogAbortRecord(TimestampTz abort_time,
    6010              :                    int nsubxacts, TransactionId *subxacts,
    6011              :                    int nrels, RelFileLocator *rels,
    6012              :                    int ndroppedstats, xl_xact_stats_item *droppedstats,
    6013              :                    int xactflags, TransactionId twophase_xid,
    6014              :                    const char *twophase_gid)
    6015              : {
    6016              :     xl_xact_abort xlrec;
    6017              :     xl_xact_xinfo xl_xinfo;
    6018              :     xl_xact_subxacts xl_subxacts;
    6019              :     xl_xact_relfilelocators xl_relfilelocators;
    6020              :     xl_xact_stats_items xl_dropped_stats;
    6021              :     xl_xact_twophase xl_twophase;
    6022              :     xl_xact_dbinfo xl_dbinfo;
    6023              :     xl_xact_origin xl_origin;
    6024              : 
    6025              :     uint8       info;
    6026              : 
    6027              :     Assert(CritSectionCount > 0);
    6028              : 
    6029         8678 :     xl_xinfo.xinfo = 0;
    6030              : 
    6031              :     /* decide between a plain and 2pc abort */
    6032         8678 :     if (!TransactionIdIsValid(twophase_xid))
    6033         8629 :         info = XLOG_XACT_ABORT;
    6034              :     else
    6035           49 :         info = XLOG_XACT_ABORT_PREPARED;
    6036              : 
    6037              : 
    6038              :     /* First figure out and collect all the information needed */
    6039              : 
    6040         8678 :     xlrec.xact_time = abort_time;
    6041              : 
    6042         8678 :     if ((xactflags & XACT_FLAGS_ACQUIREDACCESSEXCLUSIVELOCK))
    6043         3970 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS;
    6044              : 
    6045         8678 :     if (nsubxacts > 0)
    6046              :     {
    6047          108 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_SUBXACTS;
    6048          108 :         xl_subxacts.nsubxacts = nsubxacts;
    6049              :     }
    6050              : 
    6051         8678 :     if (nrels > 0)
    6052              :     {
    6053         1367 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_RELFILELOCATORS;
    6054         1367 :         xl_relfilelocators.nrels = nrels;
    6055         1367 :         info |= XLR_SPECIAL_REL_UPDATE;
    6056              :     }
    6057              : 
    6058         8678 :     if (ndroppedstats > 0)
    6059              :     {
    6060         1943 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_DROPPED_STATS;
    6061         1943 :         xl_dropped_stats.nitems = ndroppedstats;
    6062              :     }
    6063              : 
    6064         8678 :     if (TransactionIdIsValid(twophase_xid))
    6065              :     {
    6066           49 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_TWOPHASE;
    6067           49 :         xl_twophase.xid = twophase_xid;
    6068              :         Assert(twophase_gid != NULL);
    6069              : 
    6070           49 :         if (XLogLogicalInfoActive())
    6071           13 :             xl_xinfo.xinfo |= XACT_XINFO_HAS_GID;
    6072              :     }
    6073              : 
    6074         8678 :     if (TransactionIdIsValid(twophase_xid) && XLogLogicalInfoActive())
    6075              :     {
    6076           13 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_DBINFO;
    6077           13 :         xl_dbinfo.dbId = MyDatabaseId;
    6078           13 :         xl_dbinfo.tsId = MyDatabaseTableSpace;
    6079              :     }
    6080              : 
    6081              :     /*
    6082              :      * Dump transaction origin information. We need this during recovery to
    6083              :      * update the replication origin progress.
    6084              :      */
    6085         8678 :     if (replorigin_xact_state.origin != InvalidReplOriginId)
    6086              :     {
    6087           30 :         xl_xinfo.xinfo |= XACT_XINFO_HAS_ORIGIN;
    6088              : 
    6089           30 :         xl_origin.origin_lsn = replorigin_xact_state.origin_lsn;
    6090           30 :         xl_origin.origin_timestamp = replorigin_xact_state.origin_timestamp;
    6091              :     }
    6092              : 
    6093         8678 :     if (xl_xinfo.xinfo != 0)
    6094         4667 :         info |= XLOG_XACT_HAS_INFO;
    6095              : 
    6096              :     /* Then include all the collected data into the abort record. */
    6097              : 
    6098         8678 :     XLogBeginInsert();
    6099              : 
    6100         8678 :     XLogRegisterData(&xlrec, MinSizeOfXactAbort);
    6101              : 
    6102         8678 :     if (xl_xinfo.xinfo != 0)
    6103         4667 :         XLogRegisterData(&xl_xinfo, sizeof(xl_xinfo));
    6104              : 
    6105         8678 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_DBINFO)
    6106           13 :         XLogRegisterData(&xl_dbinfo, sizeof(xl_dbinfo));
    6107              : 
    6108         8678 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_SUBXACTS)
    6109              :     {
    6110          108 :         XLogRegisterData(&xl_subxacts,
    6111              :                          MinSizeOfXactSubxacts);
    6112          108 :         XLogRegisterData(subxacts,
    6113              :                          nsubxacts * sizeof(TransactionId));
    6114              :     }
    6115              : 
    6116         8678 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
    6117              :     {
    6118         1367 :         XLogRegisterData(&xl_relfilelocators,
    6119              :                          MinSizeOfXactRelfileLocators);
    6120         1367 :         XLogRegisterData(rels,
    6121              :                          nrels * sizeof(RelFileLocator));
    6122              :     }
    6123              : 
    6124         8678 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_DROPPED_STATS)
    6125              :     {
    6126         1943 :         XLogRegisterData(&xl_dropped_stats,
    6127              :                          MinSizeOfXactStatsItems);
    6128         1943 :         XLogRegisterData(droppedstats,
    6129              :                          ndroppedstats * sizeof(xl_xact_stats_item));
    6130              :     }
    6131              : 
    6132         8678 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_TWOPHASE)
    6133              :     {
    6134           49 :         XLogRegisterData(&xl_twophase, sizeof(xl_xact_twophase));
    6135           49 :         if (xl_xinfo.xinfo & XACT_XINFO_HAS_GID)
    6136           13 :             XLogRegisterData(twophase_gid, strlen(twophase_gid) + 1);
    6137              :     }
    6138              : 
    6139         8678 :     if (xl_xinfo.xinfo & XACT_XINFO_HAS_ORIGIN)
    6140           30 :         XLogRegisterData(&xl_origin, sizeof(xl_xact_origin));
    6141              : 
    6142              :     /* Include the replication origin */
    6143         8678 :     XLogSetRecordFlags(XLOG_INCLUDE_ORIGIN);
    6144              : 
    6145         8678 :     return XLogInsert(RM_XACT_ID, info);
    6146              : }
    6147              : 
    6148              : /*
    6149              :  * Before 9.0 this was a fairly short function, but now it performs many
    6150              :  * actions for which the order of execution is critical.
    6151              :  */
    6152              : static void
    6153        23276 : xact_redo_commit(xl_xact_parsed_commit *parsed,
    6154              :                  TransactionId xid,
    6155              :                  XLogRecPtr lsn,
    6156              :                  ReplOriginId origin_id)
    6157              : {
    6158              :     TransactionId max_xid;
    6159              :     TimestampTz commit_time;
    6160              : 
    6161              :     Assert(TransactionIdIsValid(xid));
    6162              : 
    6163        23276 :     max_xid = TransactionIdLatest(xid, parsed->nsubxacts, parsed->subxacts);
    6164              : 
    6165              :     /* Make sure nextXid is beyond any XID mentioned in the record. */
    6166        23276 :     AdvanceNextFullTransactionIdPastXid(max_xid);
    6167              : 
    6168              :     Assert(((parsed->xinfo & XACT_XINFO_HAS_ORIGIN) == 0) ==
    6169              :            (origin_id == InvalidReplOriginId));
    6170              : 
    6171        23276 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
    6172           20 :         commit_time = parsed->origin_timestamp;
    6173              :     else
    6174        23256 :         commit_time = parsed->xact_time;
    6175              : 
    6176              :     /* Set the transaction commit timestamp and metadata */
    6177        23276 :     TransactionTreeSetCommitTsData(xid, parsed->nsubxacts, parsed->subxacts,
    6178              :                                    commit_time, origin_id);
    6179              : 
    6180        23276 :     if (standbyState == STANDBY_DISABLED)
    6181              :     {
    6182              :         /*
    6183              :          * Mark the transaction committed in pg_xact.
    6184              :          */
    6185         2227 :         TransactionIdCommitTree(xid, parsed->nsubxacts, parsed->subxacts);
    6186              :     }
    6187              :     else
    6188              :     {
    6189              :         /*
    6190              :          * If a transaction completion record arrives that has as-yet
    6191              :          * unobserved subtransactions then this will not have been fully
    6192              :          * handled by the call to RecordKnownAssignedTransactionIds() in the
    6193              :          * main recovery loop in xlog.c. So we need to do bookkeeping again to
    6194              :          * cover that case. This is confusing and it is easy to think this
    6195              :          * call is irrelevant, which has happened three times in development
    6196              :          * already. Leave it in.
    6197              :          */
    6198        21049 :         RecordKnownAssignedTransactionIds(max_xid);
    6199              : 
    6200              :         /*
    6201              :          * Mark the transaction committed in pg_xact. We use async commit
    6202              :          * protocol during recovery to provide information on database
    6203              :          * consistency for when users try to set hint bits. It is important
    6204              :          * that we do not set hint bits until the minRecoveryPoint is past
    6205              :          * this commit record. This ensures that if we crash we don't see hint
    6206              :          * bits set on changes made by transactions that haven't yet
    6207              :          * recovered. It's unlikely but it's good to be safe.
    6208              :          */
    6209        21049 :         TransactionIdAsyncCommitTree(xid, parsed->nsubxacts, parsed->subxacts, lsn);
    6210              : 
    6211              :         /*
    6212              :          * We must mark clog before we update the ProcArray.
    6213              :          */
    6214        21049 :         ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
    6215              : 
    6216              :         /*
    6217              :          * Send any cache invalidations attached to the commit. We must
    6218              :          * maintain the same order of invalidation then release locks as
    6219              :          * occurs in CommitTransaction().
    6220              :          */
    6221        21049 :         ProcessCommittedInvalidationMessages(parsed->msgs, parsed->nmsgs,
    6222        21049 :                                              XactCompletionRelcacheInitFileInval(parsed->xinfo),
    6223              :                                              parsed->dbId, parsed->tsId);
    6224              : 
    6225              :         /*
    6226              :          * Release locks, if any. We do this for both two phase and normal one
    6227              :          * phase transactions. In effect we are ignoring the prepare phase and
    6228              :          * just going straight to lock release.
    6229              :          */
    6230        21049 :         if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
    6231        10316 :             StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
    6232              :     }
    6233              : 
    6234        23276 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
    6235              :     {
    6236              :         /* recover apply progress */
    6237           20 :         replorigin_advance(origin_id, parsed->origin_lsn, lsn,
    6238              :                            false /* backward */ , false /* WAL */ );
    6239              :     }
    6240              : 
    6241              :     /* Make sure files supposed to be dropped are dropped */
    6242        23276 :     if (parsed->nrels > 0)
    6243              :     {
    6244              :         /*
    6245              :          * First update minimum recovery point to cover this WAL record. Once
    6246              :          * a relation is deleted, there's no going back. The buffer manager
    6247              :          * enforces the WAL-first rule for normal updates to relation files,
    6248              :          * so that the minimum recovery point is always updated before the
    6249              :          * corresponding change in the data file is flushed to disk, but we
    6250              :          * have to do the same here since we're bypassing the buffer manager.
    6251              :          *
    6252              :          * Doing this before deleting the files means that if a deletion fails
    6253              :          * for some reason, you cannot start up the system even after restart,
    6254              :          * until you fix the underlying situation so that the deletion will
    6255              :          * succeed. Alternatively, we could update the minimum recovery point
    6256              :          * after deletion, but that would leave a small window where the
    6257              :          * WAL-first rule would be violated.
    6258              :          */
    6259         2209 :         XLogFlush(lsn);
    6260              : 
    6261              :         /* Make sure files supposed to be dropped are dropped */
    6262         2209 :         DropRelationFiles(parsed->xlocators, parsed->nrels, true);
    6263              :     }
    6264              : 
    6265        23276 :     if (parsed->nstats > 0)
    6266              :     {
    6267              :         /* see equivalent call for relations above */
    6268         2873 :         XLogFlush(lsn);
    6269              : 
    6270         2873 :         pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
    6271              :     }
    6272              : 
    6273              :     /*
    6274              :      * We issue an XLogFlush() for the same reason we emit ForceSyncCommit()
    6275              :      * in normal operation. For example, in CREATE DATABASE, we copy all files
    6276              :      * from the template database, and then commit the transaction. If we
    6277              :      * crash after all the files have been copied but before the commit, you
    6278              :      * have files in the data directory without an entry in pg_database. To
    6279              :      * minimize the window for that, we use ForceSyncCommit() to rush the
    6280              :      * commit record to disk as quick as possible. We have the same window
    6281              :      * during recovery, and forcing an XLogFlush() (which updates
    6282              :      * minRecoveryPoint during recovery) helps to reduce that problem window,
    6283              :      * for any user that requested ForceSyncCommit().
    6284              :      */
    6285        23276 :     if (XactCompletionForceSyncCommit(parsed->xinfo))
    6286           49 :         XLogFlush(lsn);
    6287              : 
    6288              :     /*
    6289              :      * If asked by the primary (because someone is waiting for a synchronous
    6290              :      * commit = remote_apply), we will need to ask walreceiver to send a reply
    6291              :      * immediately.
    6292              :      */
    6293        23276 :     if (XactCompletionApplyFeedback(parsed->xinfo))
    6294            2 :         XLogRequestWalReceiverReply();
    6295        23276 : }
    6296              : 
    6297              : /*
    6298              :  * Be careful with the order of execution, as with xact_redo_commit().
    6299              :  * The two functions are similar but differ in key places.
    6300              :  *
    6301              :  * Note also that an abort can be for a subtransaction and its children,
    6302              :  * not just for a top level abort. That means we have to consider
    6303              :  * topxid != xid, whereas in commit we would find topxid == xid always
    6304              :  * because subtransaction commit is never WAL logged.
    6305              :  */
    6306              : static void
    6307         1963 : xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid,
    6308              :                 XLogRecPtr lsn, ReplOriginId origin_id)
    6309              : {
    6310              :     TransactionId max_xid;
    6311              : 
    6312              :     Assert(TransactionIdIsValid(xid));
    6313              : 
    6314              :     /* Make sure nextXid is beyond any XID mentioned in the record. */
    6315         1963 :     max_xid = TransactionIdLatest(xid,
    6316              :                                   parsed->nsubxacts,
    6317         1963 :                                   parsed->subxacts);
    6318         1963 :     AdvanceNextFullTransactionIdPastXid(max_xid);
    6319              : 
    6320         1963 :     if (standbyState == STANDBY_DISABLED)
    6321              :     {
    6322              :         /* Mark the transaction aborted in pg_xact, no need for async stuff */
    6323           20 :         TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
    6324              :     }
    6325              :     else
    6326              :     {
    6327              :         /*
    6328              :          * If a transaction completion record arrives that has as-yet
    6329              :          * unobserved subtransactions then this will not have been fully
    6330              :          * handled by the call to RecordKnownAssignedTransactionIds() in the
    6331              :          * main recovery loop in xlog.c. So we need to do bookkeeping again to
    6332              :          * cover that case. This is confusing and it is easy to think this
    6333              :          * call is irrelevant, which has happened three times in development
    6334              :          * already. Leave it in.
    6335              :          */
    6336         1943 :         RecordKnownAssignedTransactionIds(max_xid);
    6337              : 
    6338              :         /* Mark the transaction aborted in pg_xact, no need for async stuff */
    6339         1943 :         TransactionIdAbortTree(xid, parsed->nsubxacts, parsed->subxacts);
    6340              : 
    6341              :         /*
    6342              :          * We must update the ProcArray after we have marked clog.
    6343              :          */
    6344         1943 :         ExpireTreeKnownAssignedTransactionIds(xid, parsed->nsubxacts, parsed->subxacts, max_xid);
    6345              : 
    6346              :         /*
    6347              :          * There are no invalidation messages to send or undo.
    6348              :          */
    6349              : 
    6350              :         /*
    6351              :          * Release locks, if any. There are no invalidations to send.
    6352              :          */
    6353         1943 :         if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS)
    6354         1253 :             StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts);
    6355              :     }
    6356              : 
    6357         1963 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
    6358              :     {
    6359              :         /* recover apply progress */
    6360            5 :         replorigin_advance(origin_id, parsed->origin_lsn, lsn,
    6361              :                            false /* backward */ , false /* WAL */ );
    6362              :     }
    6363              : 
    6364              :     /* Make sure files supposed to be dropped are dropped */
    6365         1963 :     if (parsed->nrels > 0)
    6366              :     {
    6367              :         /*
    6368              :          * See comments about update of minimum recovery point on truncation,
    6369              :          * in xact_redo_commit().
    6370              :          */
    6371          329 :         XLogFlush(lsn);
    6372              : 
    6373          329 :         DropRelationFiles(parsed->xlocators, parsed->nrels, true);
    6374              :     }
    6375              : 
    6376         1963 :     if (parsed->nstats > 0)
    6377              :     {
    6378              :         /* see equivalent call for relations above */
    6379          455 :         XLogFlush(lsn);
    6380              : 
    6381          455 :         pgstat_execute_transactional_drops(parsed->nstats, parsed->stats, true);
    6382              :     }
    6383         1963 : }
    6384              : 
    6385              : void
    6386        25594 : xact_redo(XLogReaderState *record)
    6387              : {
    6388        25594 :     uint8       info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
    6389              : 
    6390              :     /* Backup blocks are not used in xact records */
    6391              :     Assert(!XLogRecHasAnyBlockRefs(record));
    6392              : 
    6393        25594 :     if (info == XLOG_XACT_COMMIT)
    6394              :     {
    6395        23230 :         xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
    6396              :         xl_xact_parsed_commit parsed;
    6397              : 
    6398        23230 :         ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
    6399        23230 :         xact_redo_commit(&parsed, XLogRecGetXid(record),
    6400        23230 :                          record->EndRecPtr, XLogRecGetOrigin(record));
    6401              :     }
    6402         2364 :     else if (info == XLOG_XACT_COMMIT_PREPARED)
    6403              :     {
    6404           46 :         xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record);
    6405              :         xl_xact_parsed_commit parsed;
    6406              : 
    6407           46 :         ParseCommitRecord(XLogRecGetInfo(record), xlrec, &parsed);
    6408           46 :         xact_redo_commit(&parsed, parsed.twophase_xid,
    6409           46 :                          record->EndRecPtr, XLogRecGetOrigin(record));
    6410              : 
    6411              :         /* Delete TwoPhaseState gxact entry and/or 2PC file. */
    6412           46 :         LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
    6413           46 :         PrepareRedoRemove(parsed.twophase_xid, false);
    6414           46 :         LWLockRelease(TwoPhaseStateLock);
    6415              :     }
    6416         2318 :     else if (info == XLOG_XACT_ABORT)
    6417              :     {
    6418         1938 :         xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
    6419              :         xl_xact_parsed_abort parsed;
    6420              : 
    6421         1938 :         ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
    6422         1938 :         xact_redo_abort(&parsed, XLogRecGetXid(record),
    6423         1938 :                         record->EndRecPtr, XLogRecGetOrigin(record));
    6424              :     }
    6425          380 :     else if (info == XLOG_XACT_ABORT_PREPARED)
    6426              :     {
    6427           25 :         xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record);
    6428              :         xl_xact_parsed_abort parsed;
    6429              : 
    6430           25 :         ParseAbortRecord(XLogRecGetInfo(record), xlrec, &parsed);
    6431           25 :         xact_redo_abort(&parsed, parsed.twophase_xid,
    6432           25 :                         record->EndRecPtr, XLogRecGetOrigin(record));
    6433              : 
    6434              :         /* Delete TwoPhaseState gxact entry and/or 2PC file. */
    6435           25 :         LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
    6436           25 :         PrepareRedoRemove(parsed.twophase_xid, false);
    6437           25 :         LWLockRelease(TwoPhaseStateLock);
    6438              :     }
    6439          355 :     else if (info == XLOG_XACT_PREPARE)
    6440              :     {
    6441              :         /*
    6442              :          * Store xid and start/end pointers of the WAL record in TwoPhaseState
    6443              :          * gxact entry.
    6444              :          */
    6445           81 :         LWLockAcquire(TwoPhaseStateLock, LW_EXCLUSIVE);
    6446           81 :         PrepareRedoAdd(InvalidFullTransactionId,
    6447           81 :                        XLogRecGetData(record),
    6448              :                        record->ReadRecPtr,
    6449              :                        record->EndRecPtr,
    6450           81 :                        XLogRecGetOrigin(record));
    6451           81 :         LWLockRelease(TwoPhaseStateLock);
    6452              :     }
    6453          274 :     else if (info == XLOG_XACT_ASSIGNMENT)
    6454              :     {
    6455           21 :         xl_xact_assignment *xlrec = (xl_xact_assignment *) XLogRecGetData(record);
    6456              : 
    6457           21 :         if (standbyState >= STANDBY_INITIALIZED)
    6458           21 :             ProcArrayApplyXidAssignment(xlrec->xtop,
    6459           21 :                                         xlrec->nsubxacts, xlrec->xsub);
    6460              :     }
    6461          253 :     else if (info == XLOG_XACT_INVALIDATIONS)
    6462              :     {
    6463              :         /*
    6464              :          * XXX we do ignore this for now, what matters are invalidations
    6465              :          * written into the commit record.
    6466              :          */
    6467              :     }
    6468              :     else
    6469            0 :         elog(PANIC, "xact_redo: unknown op code %u", info);
    6470        25594 : }
        

Generated by: LCOV version 2.0-1