- list_free(s->childXids);
- s->childXids = NIL;
-}
-
-/*
- * RecordSubTransactionAbort
- */
-static void
-RecordSubTransactionAbort(void)
-{
- int nrels;
- RelFileNode *rels;
- TransactionId xid = GetCurrentTransactionId();
- int nchildren;
- TransactionId *children;
-
- /* Get data needed for abort record */
- nrels = smgrGetPendingDeletes(false, &rels);
- nchildren = xactGetCommittedChildren(&children);
-
- /*
- * If we made neither any transaction-controlled XLOG entries nor any
- * temp-rel updates, and are not going to delete any files, we can omit
- * recording the transaction abort at all. No one will ever care that it
- * aborted. (These tests cover our whole transaction tree, and therefore
- * may mark subxacts that don't really need it, but it's probably not
- * worth being tenser.)
- *
- * In this case we needn't worry about marking subcommitted children as
- * aborted, because they didn't mark themselves as subcommitted in the
- * first place; see the optimization in RecordSubTransactionCommit.
- */
- if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0)
- {
- START_CRIT_SECTION();
-
- /*
- * We only need to log the abort in XLOG if the transaction made any
- * transaction-controlled XLOG entries or will delete files.
- */
- if (MyLastRecPtr.xrecoff != 0 || nrels > 0)
- {
- XLogRecData rdata[3];
- int lastrdata = 0;
- xl_xact_abort xlrec;
- XLogRecPtr recptr;
-
- xlrec.xtime = time(NULL);
- xlrec.nrels = nrels;
- xlrec.nsubxacts = nchildren;
- rdata[0].data = (char *) (&xlrec);
- rdata[0].len = MinSizeOfXactAbort;
- rdata[0].buffer = InvalidBuffer;
- /* dump rels to delete */
- if (nrels > 0)
- {
- rdata[0].next = &(rdata[1]);
- rdata[1].data = (char *) rels;
- rdata[1].len = nrels * sizeof(RelFileNode);
- rdata[1].buffer = InvalidBuffer;
- lastrdata = 1;
- }
- /* dump committed child Xids */
- if (nchildren > 0)
- {
- rdata[lastrdata].next = &(rdata[2]);
- rdata[2].data = (char *) children;
- rdata[2].len = nchildren * sizeof(TransactionId);
- rdata[2].buffer = InvalidBuffer;
- lastrdata = 2;
- }
- rdata[lastrdata].next = NULL;
-
- recptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ABORT, rdata);
-
- /* Must flush if we are deleting files... */
- if (nrels > 0)
- XLogFlush(recptr);
- }
-
- /*
- * Mark the transaction aborted in clog. This is not absolutely
- * necessary but XactLockTableWait makes use of it to avoid waiting
- * for already-aborted subtransactions.
- */
- TransactionIdAbort(xid);
- TransactionIdAbortTree(nchildren, children);
-
- END_CRIT_SECTION();
- }
-
- /*
- * We can immediately remove failed XIDs from PGPROC's cache of running
- * child XIDs. It's easiest to do it here while we have the child XID
- * array at hand, even though in the main-transaction case the equivalent
- * work happens just after return from RecordTransactionAbort.
- */
- XidCacheRemoveRunningXids(xid, nchildren, children);
-
- /* And clean up local data */
- if (rels)
- pfree(rels);
- if (children)
- pfree(children);