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 + -
显示快捷键?