mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Back-patch Heikki's fix to make TransactionIdIsCurrentTransactionId() use
binary search instead of linear search when checking child-transaction XIDs. Per example from Robert Treat, the speed of TransactionIdIsCurrentTransactionId is significantly more important in 8.3 than it was in prior releases, so this seems worth taking back-patching risk for.
This commit is contained in:
		@@ -7,7 +7,7 @@
 | 
				
			|||||||
 * Portions Copyright (c) 1994, Regents of the University of California
 | 
					 * Portions Copyright (c) 1994, Regents of the University of California
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *		$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.39 2008/01/01 19:45:48 momjian Exp $
 | 
					 *		$PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.39.2.1 2008/04/26 23:35:33 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * NOTES
 | 
					 * NOTES
 | 
				
			||||||
 *		Each global transaction is associated with a global transaction
 | 
					 *		Each global transaction is associated with a global transaction
 | 
				
			||||||
@@ -827,7 +827,6 @@ StartPrepare(GlobalTransaction gxact)
 | 
				
			|||||||
		save_state_data(children, hdr.nsubxacts * sizeof(TransactionId));
 | 
							save_state_data(children, hdr.nsubxacts * sizeof(TransactionId));
 | 
				
			||||||
		/* While we have the child-xact data, stuff it in the gxact too */
 | 
							/* While we have the child-xact data, stuff it in the gxact too */
 | 
				
			||||||
		GXactLoadSubxactData(gxact, hdr.nsubxacts, children);
 | 
							GXactLoadSubxactData(gxact, hdr.nsubxacts, children);
 | 
				
			||||||
		pfree(children);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (hdr.ncommitrels > 0)
 | 
						if (hdr.ncommitrels > 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * IDENTIFICATION
 | 
					 * IDENTIFICATION
 | 
				
			||||||
 *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.257.2.1 2008/03/04 19:54:13 tgl Exp $
 | 
					 *	  $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.257.2.2 2008/04/26 23:35:33 tgl Exp $
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *-------------------------------------------------------------------------
 | 
					 *-------------------------------------------------------------------------
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@@ -130,7 +130,9 @@ typedef struct TransactionStateData
 | 
				
			|||||||
	int			gucNestLevel;	/* GUC context nesting depth */
 | 
						int			gucNestLevel;	/* GUC context nesting depth */
 | 
				
			||||||
	MemoryContext curTransactionContext;		/* my xact-lifetime context */
 | 
						MemoryContext curTransactionContext;		/* my xact-lifetime context */
 | 
				
			||||||
	ResourceOwner curTransactionOwner;	/* my query resources */
 | 
						ResourceOwner curTransactionOwner;	/* my query resources */
 | 
				
			||||||
	List	   *childXids;		/* subcommitted child XIDs */
 | 
						TransactionId *childXids;	/* subcommitted child XIDs, in XID order */
 | 
				
			||||||
 | 
						int			nChildXids;		/* # of subcommitted child XIDs */
 | 
				
			||||||
 | 
						int			maxChildXids;	/* allocated size of childXids[] */
 | 
				
			||||||
	Oid			prevUser;		/* previous CurrentUserId setting */
 | 
						Oid			prevUser;		/* previous CurrentUserId setting */
 | 
				
			||||||
	bool		prevSecDefCxt;	/* previous SecurityDefinerContext setting */
 | 
						bool		prevSecDefCxt;	/* previous SecurityDefinerContext setting */
 | 
				
			||||||
	bool		prevXactReadOnly;		/* entry-time xact r/o state */
 | 
						bool		prevXactReadOnly;		/* entry-time xact r/o state */
 | 
				
			||||||
@@ -156,7 +158,9 @@ static TransactionStateData TopTransactionStateData = {
 | 
				
			|||||||
	0,							/* GUC context nesting depth */
 | 
						0,							/* GUC context nesting depth */
 | 
				
			||||||
	NULL,						/* cur transaction context */
 | 
						NULL,						/* cur transaction context */
 | 
				
			||||||
	NULL,						/* cur transaction resource owner */
 | 
						NULL,						/* cur transaction resource owner */
 | 
				
			||||||
	NIL,						/* subcommitted child Xids */
 | 
						NULL,						/* subcommitted child Xids */
 | 
				
			||||||
 | 
						0,							/* # of subcommitted child Xids */
 | 
				
			||||||
 | 
						0,							/* allocated size of childXids[] */
 | 
				
			||||||
	InvalidOid,					/* previous CurrentUserId setting */
 | 
						InvalidOid,					/* previous CurrentUserId setting */
 | 
				
			||||||
	false,						/* previous SecurityDefinerContext setting */
 | 
						false,						/* previous SecurityDefinerContext setting */
 | 
				
			||||||
	false,						/* entry-time xact r/o state */
 | 
						false,						/* entry-time xact r/o state */
 | 
				
			||||||
@@ -559,7 +563,7 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	for (s = CurrentTransactionState; s != NULL; s = s->parent)
 | 
						for (s = CurrentTransactionState; s != NULL; s = s->parent)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		ListCell   *cell;
 | 
							int low, high;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (s->state == TRANS_ABORT)
 | 
							if (s->state == TRANS_ABORT)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
@@ -567,10 +571,22 @@ TransactionIdIsCurrentTransactionId(TransactionId xid)
 | 
				
			|||||||
			continue;			/* it can't have any child XIDs either */
 | 
								continue;			/* it can't have any child XIDs either */
 | 
				
			||||||
		if (TransactionIdEquals(xid, s->transactionId))
 | 
							if (TransactionIdEquals(xid, s->transactionId))
 | 
				
			||||||
			return true;
 | 
								return true;
 | 
				
			||||||
		foreach(cell, s->childXids)
 | 
							/* As the childXids array is ordered, we can use binary search */
 | 
				
			||||||
 | 
							low = 0;
 | 
				
			||||||
 | 
							high = s->nChildXids - 1;
 | 
				
			||||||
 | 
							while (low <= high)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (TransactionIdEquals(xid, lfirst_xid(cell)))
 | 
								int				middle;
 | 
				
			||||||
 | 
								TransactionId	probe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								middle = low + (high - low) / 2;
 | 
				
			||||||
 | 
								probe = s->childXids[middle];
 | 
				
			||||||
 | 
								if (TransactionIdEquals(probe, xid))
 | 
				
			||||||
				return true;
 | 
									return true;
 | 
				
			||||||
 | 
								else if (TransactionIdPrecedes(probe, xid))
 | 
				
			||||||
 | 
									low = middle + 1;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									high = middle - 1;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -985,8 +1001,6 @@ cleanup:
 | 
				
			|||||||
	/* Clean up local data */
 | 
						/* Clean up local data */
 | 
				
			||||||
	if (rels)
 | 
						if (rels)
 | 
				
			||||||
		pfree(rels);
 | 
							pfree(rels);
 | 
				
			||||||
	if (children)
 | 
					 | 
				
			||||||
		pfree(children);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return latestXid;
 | 
						return latestXid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1067,34 +1081,79 @@ static void
 | 
				
			|||||||
AtSubCommit_childXids(void)
 | 
					AtSubCommit_childXids(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TransactionState s = CurrentTransactionState;
 | 
						TransactionState s = CurrentTransactionState;
 | 
				
			||||||
	MemoryContext old_cxt;
 | 
						int			new_nChildXids;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Assert(s->parent != NULL);
 | 
						Assert(s->parent != NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We keep the child-XID lists in TopTransactionContext; this avoids
 | 
						 * The parent childXids array will need to hold my XID and all my
 | 
				
			||||||
 | 
						 * childXids, in addition to the XIDs already there.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						new_nChildXids = s->parent->nChildXids + s->nChildXids + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Allocate or enlarge the parent array if necessary */
 | 
				
			||||||
 | 
						if (s->parent->maxChildXids < new_nChildXids)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int				new_maxChildXids;
 | 
				
			||||||
 | 
							TransactionId  *new_childXids;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Make it 2x what's needed right now, to avoid having to enlarge it
 | 
				
			||||||
 | 
							 * repeatedly. But we can't go above MaxAllocSize.  (The latter
 | 
				
			||||||
 | 
							 * limit is what ensures that we don't need to worry about integer
 | 
				
			||||||
 | 
							 * overflow here or in the calculation of new_nChildXids.)
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							new_maxChildXids = Min(new_nChildXids * 2,
 | 
				
			||||||
 | 
												   (int) (MaxAllocSize / sizeof(TransactionId)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (new_maxChildXids < new_nChildXids)
 | 
				
			||||||
 | 
								ereport(ERROR,
 | 
				
			||||||
 | 
										(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 | 
				
			||||||
 | 
										 errmsg("maximum number of committed subtransactions (%d) exceeded",
 | 
				
			||||||
 | 
												(int) (MaxAllocSize / sizeof(TransactionId)))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * We keep the child-XID arrays in TopTransactionContext; this avoids
 | 
				
			||||||
		 * setting up child-transaction contexts for what might be just a few
 | 
							 * setting up child-transaction contexts for what might be just a few
 | 
				
			||||||
		 * bytes of grandchild XIDs.
 | 
							 * bytes of grandchild XIDs.
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
	old_cxt = MemoryContextSwitchTo(TopTransactionContext);
 | 
							if (s->parent->childXids == NULL)
 | 
				
			||||||
 | 
								new_childXids =
 | 
				
			||||||
 | 
									MemoryContextAlloc(TopTransactionContext, 
 | 
				
			||||||
 | 
													   new_maxChildXids * sizeof(TransactionId));
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								new_childXids = repalloc(s->parent->childXids, 
 | 
				
			||||||
 | 
														 new_maxChildXids * sizeof(TransactionId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	s->parent->childXids = lappend_xid(s->parent->childXids,
 | 
							s->parent->childXids  = new_childXids;
 | 
				
			||||||
									   s->transactionId);
 | 
							s->parent->maxChildXids = new_maxChildXids;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (s->childXids != NIL)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		s->parent->childXids = list_concat(s->parent->childXids,
 | 
					 | 
				
			||||||
										   s->childXids);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
					 | 
				
			||||||
		 * list_concat doesn't free the list header for the second list; do so
 | 
					 | 
				
			||||||
		 * here to avoid memory leakage (kluge)
 | 
					 | 
				
			||||||
		 */
 | 
					 | 
				
			||||||
		pfree(s->childXids);
 | 
					 | 
				
			||||||
		s->childXids = NIL;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MemoryContextSwitchTo(old_cxt);
 | 
						/*
 | 
				
			||||||
 | 
						 * Copy all my XIDs to parent's array.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Note: We rely on the fact that the XID of a child always follows that
 | 
				
			||||||
 | 
						 * of its parent.  By copying the XID of this subtransaction before the
 | 
				
			||||||
 | 
						 * XIDs of its children, we ensure that the array stays ordered.  Likewise,
 | 
				
			||||||
 | 
						 * all XIDs already in the array belong to subtransactions started and
 | 
				
			||||||
 | 
						 * subcommitted before us, so their XIDs must precede ours.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						s->parent->childXids[s->parent->nChildXids] = s->transactionId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (s->nChildXids > 0)
 | 
				
			||||||
 | 
							memcpy(&s->parent->childXids[s->parent->nChildXids + 1],
 | 
				
			||||||
 | 
								   s->childXids,
 | 
				
			||||||
 | 
								   s->nChildXids * sizeof(TransactionId));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s->parent->nChildXids = new_nChildXids;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Release child's array to avoid leakage */
 | 
				
			||||||
 | 
						if (s->childXids != NULL)
 | 
				
			||||||
 | 
							pfree(s->childXids);
 | 
				
			||||||
 | 
						/* We must reset these to avoid double-free if fail later in commit */
 | 
				
			||||||
 | 
						s->childXids = NULL;
 | 
				
			||||||
 | 
						s->nChildXids = 0;
 | 
				
			||||||
 | 
						s->maxChildXids = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -1259,8 +1318,6 @@ RecordTransactionAbort(bool isSubXact)
 | 
				
			|||||||
	/* And clean up local data */
 | 
						/* And clean up local data */
 | 
				
			||||||
	if (rels)
 | 
						if (rels)
 | 
				
			||||||
		pfree(rels);
 | 
							pfree(rels);
 | 
				
			||||||
	if (children)
 | 
					 | 
				
			||||||
		pfree(children);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return latestXid;
 | 
						return latestXid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1332,12 +1389,15 @@ AtSubAbort_childXids(void)
 | 
				
			|||||||
	TransactionState s = CurrentTransactionState;
 | 
						TransactionState s = CurrentTransactionState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * We keep the child-XID lists in TopTransactionContext (see
 | 
						 * We keep the child-XID arrays in TopTransactionContext (see
 | 
				
			||||||
	 * AtSubCommit_childXids).	This means we'd better free the list
 | 
						 * AtSubCommit_childXids).	This means we'd better free the array
 | 
				
			||||||
	 * explicitly at abort to avoid leakage.
 | 
						 * explicitly at abort to avoid leakage.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	list_free(s->childXids);
 | 
						if (s->childXids != NULL)
 | 
				
			||||||
	s->childXids = NIL;
 | 
							pfree(s->childXids);
 | 
				
			||||||
 | 
						s->childXids = NULL;
 | 
				
			||||||
 | 
						s->nChildXids = 0;
 | 
				
			||||||
 | 
						s->maxChildXids = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ----------------------------------------------------------------
 | 
					/* ----------------------------------------------------------------
 | 
				
			||||||
@@ -1506,7 +1566,9 @@ StartTransaction(void)
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	s->nestingLevel = 1;
 | 
						s->nestingLevel = 1;
 | 
				
			||||||
	s->gucNestLevel = 1;
 | 
						s->gucNestLevel = 1;
 | 
				
			||||||
	s->childXids = NIL;
 | 
						s->childXids = NULL;
 | 
				
			||||||
 | 
						s->nChildXids = 0;
 | 
				
			||||||
 | 
						s->maxChildXids = 0;
 | 
				
			||||||
	GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
 | 
						GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt);
 | 
				
			||||||
	/* SecurityDefinerContext should never be set outside a transaction */
 | 
						/* SecurityDefinerContext should never be set outside a transaction */
 | 
				
			||||||
	Assert(!s->prevSecDefCxt);
 | 
						Assert(!s->prevSecDefCxt);
 | 
				
			||||||
@@ -1702,7 +1764,9 @@ CommitTransaction(void)
 | 
				
			|||||||
	s->subTransactionId = InvalidSubTransactionId;
 | 
						s->subTransactionId = InvalidSubTransactionId;
 | 
				
			||||||
	s->nestingLevel = 0;
 | 
						s->nestingLevel = 0;
 | 
				
			||||||
	s->gucNestLevel = 0;
 | 
						s->gucNestLevel = 0;
 | 
				
			||||||
	s->childXids = NIL;
 | 
						s->childXids = NULL;
 | 
				
			||||||
 | 
						s->nChildXids = 0;
 | 
				
			||||||
 | 
						s->maxChildXids = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * done with commit processing, set current transaction state back to
 | 
						 * done with commit processing, set current transaction state back to
 | 
				
			||||||
@@ -1931,7 +1995,9 @@ PrepareTransaction(void)
 | 
				
			|||||||
	s->subTransactionId = InvalidSubTransactionId;
 | 
						s->subTransactionId = InvalidSubTransactionId;
 | 
				
			||||||
	s->nestingLevel = 0;
 | 
						s->nestingLevel = 0;
 | 
				
			||||||
	s->gucNestLevel = 0;
 | 
						s->gucNestLevel = 0;
 | 
				
			||||||
	s->childXids = NIL;
 | 
						s->childXids = NULL;
 | 
				
			||||||
 | 
						s->nChildXids = 0;
 | 
				
			||||||
 | 
						s->maxChildXids = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * done with 1st phase commit processing, set current transaction state
 | 
						 * done with 1st phase commit processing, set current transaction state
 | 
				
			||||||
@@ -2101,7 +2167,9 @@ CleanupTransaction(void)
 | 
				
			|||||||
	s->subTransactionId = InvalidSubTransactionId;
 | 
						s->subTransactionId = InvalidSubTransactionId;
 | 
				
			||||||
	s->nestingLevel = 0;
 | 
						s->nestingLevel = 0;
 | 
				
			||||||
	s->gucNestLevel = 0;
 | 
						s->gucNestLevel = 0;
 | 
				
			||||||
	s->childXids = NIL;
 | 
						s->childXids = NULL;
 | 
				
			||||||
 | 
						s->nChildXids = 0;
 | 
				
			||||||
 | 
						s->maxChildXids = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * done with abort processing, set current transaction state back to
 | 
						 * done with abort processing, set current transaction state back to
 | 
				
			||||||
@@ -4051,6 +4119,19 @@ ShowTransactionState(const char *str)
 | 
				
			|||||||
static void
 | 
					static void
 | 
				
			||||||
ShowTransactionStateRec(TransactionState s)
 | 
					ShowTransactionStateRec(TransactionState s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						StringInfoData buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						initStringInfo(&buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (s->nChildXids > 0)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							appendStringInfo(&buf, "%u", s->childXids[0]);
 | 
				
			||||||
 | 
							for (i = 1; i < s->nChildXids; i++)
 | 
				
			||||||
 | 
								appendStringInfo(&buf, " %u", s->childXids[i]);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (s->parent)
 | 
						if (s->parent)
 | 
				
			||||||
		ShowTransactionStateRec(s->parent);
 | 
							ShowTransactionStateRec(s->parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4064,8 +4145,9 @@ ShowTransactionStateRec(TransactionState s)
 | 
				
			|||||||
							 (unsigned int) s->subTransactionId,
 | 
												 (unsigned int) s->subTransactionId,
 | 
				
			||||||
							 (unsigned int) currentCommandId,
 | 
												 (unsigned int) currentCommandId,
 | 
				
			||||||
							 currentCommandIdUsed ? " (used)" : "",
 | 
												 currentCommandIdUsed ? " (used)" : "",
 | 
				
			||||||
							 s->nestingLevel,
 | 
												 s->nestingLevel, buf.data)));
 | 
				
			||||||
							 nodeToString(s->childXids))));
 | 
					
 | 
				
			||||||
 | 
						pfree(buf.data);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -4144,36 +4226,22 @@ TransStateAsString(TransState state)
 | 
				
			|||||||
 * xactGetCommittedChildren
 | 
					 * xactGetCommittedChildren
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Gets the list of committed children of the current transaction.	The return
 | 
					 * Gets the list of committed children of the current transaction.	The return
 | 
				
			||||||
 * value is the number of child transactions.  *children is set to point to a
 | 
					 * value is the number of child transactions.  *ptr is set to point to an
 | 
				
			||||||
 * palloc'd array of TransactionIds.  If there are no subxacts, *children is
 | 
					 * array of TransactionIds.  The array is allocated in TopTransactionContext;
 | 
				
			||||||
 * set to NULL.
 | 
					 * the caller should *not* pfree() it (this is a change from pre-8.4 code!).
 | 
				
			||||||
 | 
					 * If there are no subxacts, *ptr is set to NULL.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int
 | 
					int
 | 
				
			||||||
xactGetCommittedChildren(TransactionId **ptr)
 | 
					xactGetCommittedChildren(TransactionId **ptr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	TransactionState s = CurrentTransactionState;
 | 
						TransactionState s = CurrentTransactionState;
 | 
				
			||||||
	int			nchildren;
 | 
					 | 
				
			||||||
	TransactionId *children;
 | 
					 | 
				
			||||||
	ListCell   *p;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nchildren = list_length(s->childXids);
 | 
						if (s->nChildXids == 0)
 | 
				
			||||||
	if (nchildren == 0)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		*ptr = NULL;
 | 
							*ptr = NULL;
 | 
				
			||||||
		return 0;
 | 
						else
 | 
				
			||||||
	}
 | 
							*ptr = s->childXids;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	children = (TransactionId *) palloc(nchildren * sizeof(TransactionId));
 | 
						return s->nChildXids;
 | 
				
			||||||
	*ptr = children;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	foreach(p, s->childXids)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		TransactionId child = lfirst_xid(p);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		*children++ = child;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nchildren;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user