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