portalmem.c

来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 759 行 · 第 1/2 页

C
759
字号
	/* release portal struct (it's in PortalMemory) */	pfree(portal);}/* * DropDependentPortals *		Drop any portals using the specified context as queryContext. * * This is normally used to make sure we can safely drop a prepared statement. */voidDropDependentPortals(MemoryContext queryContext){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		if (portal->queryContext == queryContext)			PortalDrop(portal, false);	}}/* * Pre-commit processing for portals. * * Any holdable cursors created in this transaction need to be converted to * materialized form, since we are going to close down the executor and * release locks.  Other portals are not touched yet. * * Returns TRUE if any holdable cursors were processed, FALSE if not. */boolCommitHoldablePortals(void){	bool		result = false;	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		/* Is it a holdable portal created in the current xact? */		if ((portal->cursorOptions & CURSOR_OPT_HOLD) &&			portal->createSubid != InvalidSubTransactionId &&			portal->status == PORTAL_READY)		{			/*			 * We are exiting the transaction that created a holdable cursor.			 * Instead of dropping the portal, prepare it for access by later			 * transactions.			 *			 * Note that PersistHoldablePortal() must release all resources			 * used by the portal that are local to the creating transaction.			 */			PortalCreateHoldStore(portal);			PersistHoldablePortal(portal);			/*			 * Any resources belonging to the portal will be released in the			 * upcoming transaction-wide cleanup; the portal will no longer			 * have its own resources.			 */			portal->resowner = NULL;			/*			 * Having successfully exported the holdable cursor, mark it as			 * not belonging to this transaction.			 */			portal->createSubid = InvalidSubTransactionId;			result = true;		}	}	return result;}/* * Pre-prepare processing for portals. * * Currently we refuse PREPARE if the transaction created any holdable * cursors, since it's quite unclear what to do with one.  However, this * has the same API as CommitHoldablePortals and is invoked in the same * way by xact.c, so that we can easily do something reasonable if anyone * comes up with something reasonable to do. * * Returns TRUE if any holdable cursors were processed, FALSE if not. */boolPrepareHoldablePortals(void){	bool		result = false;	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		/* Is it a holdable portal created in the current xact? */		if ((portal->cursorOptions & CURSOR_OPT_HOLD) &&			portal->createSubid != InvalidSubTransactionId &&			portal->status == PORTAL_READY)		{			/*			 * We are exiting the transaction that created a holdable cursor.			 * Can't do PREPARE.			 */			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("cannot PREPARE a transaction that has created a cursor WITH HOLD")));		}	}	return result;}/* * Pre-commit processing for portals. * * Remove all non-holdable portals created in this transaction. * Portals remaining from prior transactions should be left untouched. */voidAtCommit_Portals(void){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		/*		 * Do not touch active portals --- this can only happen in the case of		 * a multi-transaction utility command, such as VACUUM.		 *		 * Note however that any resource owner attached to such a portal is		 * still going to go away, so don't leave a dangling pointer.		 */		if (portal->status == PORTAL_ACTIVE)		{			portal->resowner = NULL;			continue;		}		/*		 * Do nothing to cursors held over from a previous transaction		 * (including holdable ones just frozen by CommitHoldablePortals).		 */		if (portal->createSubid == InvalidSubTransactionId)			continue;		/* Zap all non-holdable portals */		PortalDrop(portal, true);		/* Restart the iteration */		hash_seq_init(&status, PortalHashTable);	}}/* * Abort processing for portals. * * At this point we reset "active" status and run the cleanup hook if * present, but we can't release memory until the cleanup call. * * The reason we need to reset active is so that we can replace the unnamed * portal, else we'll fail to execute ROLLBACK when it arrives. */voidAtAbort_Portals(void){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		if (portal->status == PORTAL_ACTIVE)			portal->status = PORTAL_FAILED;		/*		 * Do nothing else to cursors held over from a previous transaction.		 */		if (portal->createSubid == InvalidSubTransactionId)			continue;		/* let portalcmds.c clean up the state it knows about */		if (PointerIsValid(portal->cleanup))		{			(*portal->cleanup) (portal);			portal->cleanup = NULL;		}		/*		 * Any resources belonging to the portal will be released in the		 * upcoming transaction-wide cleanup; they will be gone before we run		 * PortalDrop.		 */		portal->resowner = NULL;	}}/* * Post-abort cleanup for portals. * * Delete all portals not held over from prior transactions.  */voidAtCleanup_Portals(void){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		/* Do nothing to cursors held over from a previous transaction */		if (portal->createSubid == InvalidSubTransactionId)		{			Assert(portal->status != PORTAL_ACTIVE);			Assert(portal->resowner == NULL);			continue;		}		/* Else zap it. */		PortalDrop(portal, false);	}}/* * Pre-subcommit processing for portals. * * Reassign the portals created in the current subtransaction to the parent * subtransaction. */voidAtSubCommit_Portals(SubTransactionId mySubid,					SubTransactionId parentSubid,					ResourceOwner parentXactOwner){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		if (portal->createSubid == mySubid)		{			portal->createSubid = parentSubid;			if (portal->resowner)				ResourceOwnerNewParent(portal->resowner, parentXactOwner);		}	}}/* * Subtransaction abort handling for portals. * * Deactivate portals created during the failed subtransaction. * Note that per AtSubCommit_Portals, this will catch portals created * in descendants of the subtransaction too. * * We don't destroy any portals here; that's done in AtSubCleanup_Portals. */voidAtSubAbort_Portals(SubTransactionId mySubid,				   SubTransactionId parentSubid,				   ResourceOwner parentXactOwner){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		if (portal->createSubid != mySubid)			continue;		/*		 * Force any active portals of my own transaction into FAILED state.		 * This is mostly to ensure that a portal running a FETCH will go		 * FAILED if the underlying cursor fails.  (Note we do NOT want to do		 * this to upper-level portals, since they may be able to continue.)		 *		 * This is only needed to dodge the sanity check in PortalDrop.		 */		if (portal->status == PORTAL_ACTIVE)			portal->status = PORTAL_FAILED;		/*		 * If the portal is READY then allow it to survive into the parent		 * transaction; otherwise shut it down.		 *		 * Currently, we can't actually support that because the portal's		 * query might refer to objects created or changed in the failed		 * subtransaction, leading to crashes if execution is resumed. So,		 * even READY portals are deleted.	It would be nice to detect whether		 * the query actually depends on any such object, instead.		 */#ifdef NOT_USED		if (portal->status == PORTAL_READY)		{			portal->createSubid = parentSubid;			if (portal->resowner)				ResourceOwnerNewParent(portal->resowner, parentXactOwner);		}		else#endif		{			/* let portalcmds.c clean up the state it knows about */			if (PointerIsValid(portal->cleanup))			{				(*portal->cleanup) (portal);				portal->cleanup = NULL;			}			/*			 * Any resources belonging to the portal will be released in the			 * upcoming transaction-wide cleanup; they will be gone before we			 * run PortalDrop.			 */			portal->resowner = NULL;		}	}}/* * Post-subabort cleanup for portals. * * Drop all portals created in the failed subtransaction (but note that * we will not drop any that were reassigned to the parent above). */voidAtSubCleanup_Portals(SubTransactionId mySubid){	HASH_SEQ_STATUS status;	PortalHashEnt *hentry;	hash_seq_init(&status, PortalHashTable);	while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)	{		Portal		portal = hentry->portal;		if (portal->createSubid != mySubid)			continue;		/* Zap it. */		PortalDrop(portal, false);	}}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?