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

Generated by: LCOV version 2.0-1