diff -cr --exclude-from=diff-ignore 08simple/src/backend/access/transam/xact.c 10smgr/src/backend/access/transam/xact.c *** 08simple/src/backend/access/transam/xact.c 2004-04-20 01:25:52.000000000 -0400 --- 10smgr/src/backend/access/transam/xact.c 2004-04-25 13:34:13.376961237 -0400 *************** *** 202,207 **** --- 202,208 ---- static void AtSubStart_Memory(void); static void AtSubCommit_Memory(void); + static void AtSubAbort_Memory(void); static void AtSubCleanup_Memory(void); #else /* SUBTRANSACTIONS */ *************** *** 382,387 **** --- 383,434 ---- /* + * TransactionGetPendingDeletes + */ + List * + TransactionGetPendingDeletes(void) + { + TransactionState s = CurrentTransactionState; + + return s->pendingDeletes; + } + + /* + * TransactionSetPendingDeletes + */ + void + TransactionSetPendingDeletes(List *pending) + { + TransactionState s = CurrentTransactionState; + + s->pendingDeletes = pending; + } + + /* + * TransactionGetParentPendingDeletes + */ + List * + TransactionGetParentPendingDeletes(void) + { + TransactionState s = CurrentTransactionState; + + Assert(s->parent != NULL); + return s->parent->pendingDeletes; + } + + /* + * TransactionSetParentPendingDeletes + */ + void + TransactionSetParentPendingDeletes(List *pending) + { + TransactionState s = CurrentTransactionState; + + Assert(s->parent != NULL); + s->parent->pendingDeletes = pending; + } + + /* * TransactionIdIsCurrentTransactionId * * During bootstrap, we cheat and say "it's not my transaction ID" even though *************** *** 479,484 **** --- 526,533 ---- static void AtStart_Memory(void) { + TransactionState s = CurrentTransactionState; + /* * We shouldn't have a transaction context already. */ *************** *** 507,512 **** --- 556,563 ---- ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + + s->commitContext = CommitContext; } #ifdef SUBTRANSACTIONS *************** *** 537,542 **** --- 588,595 ---- ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); + + s->commitContext = CommitContext; } #endif /* SUBTRANSACTIONS */ *************** *** 884,889 **** --- 937,954 ---- MemoryContextSwitchTo(TopMemoryContext); } + #ifdef SUBTRANSACTIONS + /* + * AtSubAbort_Memory + */ + static void + AtSubAbort_Memory(void) + { + Assert(TopTransactionContext != NULL); + + MemoryContextSwitchTo(TopTransactionContext); + } + #endif /* ---------------------------------------------------------------- * CleanupTransaction stuff *************** *** 1002,1007 **** --- 1067,1073 ---- * progress" */ s->state = TRANS_INPROGRESS; + ShowTransactionState("StartTransaction"); } *************** *** 1013,1018 **** --- 1079,1086 ---- { TransactionState s = CurrentTransactionState; + ShowTransactionState("CommitTransaction"); + /* * check the current transaction state */ *************** *** 1267,1274 **** { TransactionState s = CurrentTransactionState; - ShowTransactionState("StartTransactionCommand"); - switch (s->blockState) { /* --- 1335,1340 ---- *************** *** 1321,1327 **** */ Assert(TopTransactionContext != NULL); MemoryContextSwitchTo(TopTransactionContext); - ShowTransactionState("End StartTransactionCommand"); } /* --- 1387,1392 ---- *************** *** 1331,1337 **** CommitTransactionCommand(void) { TransactionState s = CurrentTransactionState; - ShowTransactionState("CommitTransactionCommand"); switch (s->blockState) { --- 1396,1401 ---- *************** *** 1471,1477 **** } break; } - ShowTransactionState("End CommitTransactionCommand"); } /* --- 1535,1540 ---- *************** *** 1482,1489 **** { TransactionState s = CurrentTransactionState; - ShowTransactionState("AbortCurrentTransaction"); - switch (s->blockState) { /* --- 1545,1550 ---- *************** *** 1599,1605 **** AbortTransaction(); break; } - ShowTransactionState("End AbortCurrentTransaction"); } /* --- 1660,1665 ---- *************** *** 2134,2144 **** void StartSubTransaction(void) { ! ShowTransactionState("StartSubTransaction"); /* Initialize the memory subsystem */ AtSubStart_Memory(); } /* --- 2194,2212 ---- void StartSubTransaction(void) { ! TransactionState s = CurrentTransactionState; ! ! /* ! * generate a new transaction id ! */ ! s->transactionIdData = GetNewTransactionId(); ! ! CommandCounterIncrement(); /* Initialize the memory subsystem */ AtSubStart_Memory(); + ShowTransactionState("StartSubTransaction"); } /* *************** *** 2147,2154 **** --- 2215,2230 ---- void CommitSubTransaction(void) { + TransactionState s = CurrentTransactionState; ShowTransactionState("CommitSubTransaction"); + CommandCounterIncrement(); + + Assert(s->parent != NULL); + + smgrCommitSubTransaction(); + + AtSubCommit_Portals(s->parent->transactionIdData); AtSubCommit_Memory(); } *************** *** 2159,2164 **** --- 2235,2248 ---- AbortSubTransaction(void) { ShowTransactionState("AbortSubTransaction"); + + AtSubAbort_Portals(); + AtSubAbort_Memory(); + + /* I'm not sure this is needed. */ + CommandCounterIncrement(); + + smgrAbortSubTransaction(); } /* *************** *** 2169,2174 **** --- 2253,2259 ---- { ShowTransactionState("CleanupSubTransaction"); + AtSubCleanup_Portals(); AtSubCleanup_Memory(); } *************** *** 2186,2201 **** * Make sure the transaction state node is in a long-lived context */ old_cxt = MemoryContextSwitchTo(TopMemoryContext); - parent = (TransactionState) palloc(sizeof(TransactionStateData)); - MemoryContextSwitchTo(old_cxt); memcpy(parent, s, sizeof(TransactionStateData)); - parent->commitContext = CommitContext; s->parent = parent; s->nestingLevel = s->parent->nestingLevel + 1; s->commandId = s->parent->commandId; ! CommandCounterIncrement(); } /* --- 2271,2285 ---- * Make sure the transaction state node is in a long-lived context */ old_cxt = MemoryContextSwitchTo(TopMemoryContext); + parent = (TransactionState) palloc(sizeof(TransactionStateData)); memcpy(parent, s, sizeof(TransactionStateData)); s->parent = parent; s->nestingLevel = s->parent->nestingLevel + 1; s->commandId = s->parent->commandId; ! ! MemoryContextSwitchTo(old_cxt); } /* *************** *** 2215,2221 **** memcpy(s, p, sizeof(TransactionStateData)); CommitContext = s->commitContext; - CommandCounterIncrement(); /* Free the old parent structure */ pfree(p); --- 2299,2304 ---- *************** *** 2227,2234 **** void ShowTransactionState(char *str) { elog(DEBUG2, "%s", str); ! ShowTransactionStateRec(CurrentTransactionState, 0); } /* --- 2310,2319 ---- void ShowTransactionState(char *str) { + TransactionState s = CurrentTransactionState; + elog(DEBUG2, "%s", str); ! ShowTransactionStateRec(CurrentTransactionState, 2 * s->nestingLevel); } /* *************** *** 2237,2262 **** void ShowTransactionStateRec(TransactionState s, int indent) { ! char *i; ! char *blockState = BlockStateAsString(s->blockState); ! char *state = TransStateAsString(s->state); ! ! i = (char *)malloc(sizeof(char) * indent + 1); ! memset(i, ' ', indent); ! memset(i + indent, '\0', 1); ! elog(DEBUG1, "%sblockState: %s; state: %s, tid/cid: %u/%u, nestlvl: %d", ! i, blockState, state, (unsigned int)s->transactionIdData, ! (unsigned int)s->commandId , s->nestingLevel); ! free(i); pfree(blockState); pfree(state); - if (s->parent) - ShowTransactionStateRec(s->parent, indent + 1); } #endif /* SUBTRANSACTIONS */ --- 2322,2348 ---- void ShowTransactionStateRec(TransactionState s, int indent) { ! char *blockState = BlockStateAsString(s->blockState); ! char *state = TransStateAsString(s->state); ! char *tmp; ! ! if (s->parent) ! ShowTransactionStateRec(s->parent, indent - 2); ! tmp = (char *)malloc(sizeof(char) * indent + 1); ! memset(tmp, ' ', indent); ! memset(tmp + indent, '\0', 1); ! ! elog(DEBUG2, "%sblockState: %s; state: %s, xid/cid: %u/%u, nestlvl: %d", ! tmp, blockState, state, (unsigned int)s->transactionIdData, ! (unsigned int)s->commandId, s->nestingLevel); ! free(tmp); pfree(blockState); pfree(state); } #endif /* SUBTRANSACTIONS */ diff -cr --exclude-from=diff-ignore 08simple/src/backend/storage/smgr/smgr.c 10smgr/src/backend/storage/smgr/smgr.c *** 08simple/src/backend/storage/smgr/smgr.c 2004-04-19 17:10:12.000000000 -0400 --- 10smgr/src/backend/storage/smgr/smgr.c 2004-04-25 12:37:32.247548626 -0400 *************** *** 17,22 **** --- 17,23 ---- */ #include "postgres.h" + #include "access/xact.h" #include "storage/bufmgr.h" #include "storage/freespace.h" #include "storage/ipc.h" *************** *** 77,98 **** * executed immediately, but is just entered in the list. When and if * the transaction commits, we can delete the physical file. * ! * NOTE: the list is kept in TopMemoryContext to be sure it won't disappear ! * unbetimes. It'd probably be OK to keep it in TopTransactionContext, ! * but I'm being paranoid. */ ! typedef struct PendingRelDelete { RelFileNode relnode; /* relation that may need to be deleted */ int which; /* which storage manager? */ bool isTemp; /* is it a temporary relation? */ bool atCommit; /* T=delete at commit; F=delete at abort */ ! struct PendingRelDelete *next; /* linked-list link */ ! } PendingRelDelete; ! ! static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */ /* * Declarations for smgr-related XLOG records --- 78,95 ---- * executed immediately, but is just entered in the list. When and if * the transaction commits, we can delete the physical file. * ! * The list is kept in CommitContext. */ ! typedef struct PendingRelDeleteData { RelFileNode relnode; /* relation that may need to be deleted */ int which; /* which storage manager? */ bool isTemp; /* is it a temporary relation? */ bool atCommit; /* T=delete at commit; F=delete at abort */ ! } PendingRelDeleteData; + typedef PendingRelDeleteData *PendingRelDelete; /* * Declarations for smgr-related XLOG records *************** *** 300,306 **** XLogRecPtr lsn; XLogRecData rdata; xl_smgr_create xlrec; ! PendingRelDelete *pending; if (! (*(smgrsw[reln->smgr_which].smgr_create)) (reln, isRedo)) ereport(ERROR, --- 297,304 ---- XLogRecPtr lsn; XLogRecData rdata; xl_smgr_create xlrec; ! PendingRelDelete pending; ! MemoryContext old_cxt; if (! (*(smgrsw[reln->smgr_which].smgr_create)) (reln, isRedo)) ereport(ERROR, *************** *** 326,340 **** lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLOG_NO_TRAN, &rdata); /* Add the relation to the list of stuff to delete at abort */ ! pending = (PendingRelDelete *) ! MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete)); pending->relnode = reln->smgr_rnode; pending->which = reln->smgr_which; pending->isTemp = isTemp; pending->atCommit = false; /* delete if abort */ ! pending->next = pendingDeletes; ! pendingDeletes = pending; } /* --- 324,342 ---- lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE | XLOG_NO_TRAN, &rdata); + old_cxt = MemoryContextSwitchTo(CommitContext); + /* Add the relation to the list of stuff to delete at abort */ ! pending = (PendingRelDelete) palloc(sizeof(PendingRelDeleteData)); pending->relnode = reln->smgr_rnode; pending->which = reln->smgr_which; pending->isTemp = isTemp; pending->atCommit = false; /* delete if abort */ ! ! TransactionSetPendingDeletes(lcons(pending, ! TransactionGetPendingDeletes())); ! ! MemoryContextSwitchTo(old_cxt); } /* *************** *** 348,364 **** void smgrscheduleunlink(SMgrRelation reln, bool isTemp) { ! PendingRelDelete *pending; /* Add the relation to the list of stuff to delete at commit */ ! pending = (PendingRelDelete *) ! MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete)); pending->relnode = reln->smgr_rnode; pending->which = reln->smgr_which; pending->isTemp = isTemp; pending->atCommit = true; /* delete if commit */ ! pending->next = pendingDeletes; ! pendingDeletes = pending; /* * NOTE: if the relation was created in this transaction, it will now --- 350,369 ---- void smgrscheduleunlink(SMgrRelation reln, bool isTemp) { ! PendingRelDelete pending; ! MemoryContext old_cxt; ! ! old_cxt = MemoryContextSwitchTo(CommitContext); /* Add the relation to the list of stuff to delete at commit */ ! pending = (PendingRelDelete) palloc(sizeof(PendingRelDeleteData)); pending->relnode = reln->smgr_rnode; pending->which = reln->smgr_which; pending->isTemp = isTemp; pending->atCommit = true; /* delete if commit */ ! ! TransactionSetPendingDeletes(lcons(pending, ! TransactionGetPendingDeletes())); /* * NOTE: if the relation was created in this transaction, it will now *************** *** 372,377 **** --- 377,384 ---- /* Now close the file and throw away the hashtable entry */ smgrclose(reln); + + MemoryContextSwitchTo(old_cxt); } /* *************** *** 573,590 **** void smgrDoPendingDeletes(bool isCommit) { ! while (pendingDeletes != NULL) { ! PendingRelDelete *pending = pendingDeletes; - pendingDeletes = pending->next; if (pending->atCommit == isCommit) smgr_internal_unlink(pending->relnode, pending->which, pending->isTemp, false); - pfree(pending); } } /* --- 580,640 ---- void smgrDoPendingDeletes(bool isCommit) { ! List *p; ! ! foreach (p, TransactionGetPendingDeletes()) { ! PendingRelDelete pending = lfirst(p); if (pending->atCommit == isCommit) smgr_internal_unlink(pending->relnode, pending->which, pending->isTemp, false); } + + TransactionSetPendingDeletes(NIL); + } + + /* + * smgrAbortSubTransaction() --- Take care of subtransaction abort. + * + * Delete created relations and forget about deleted relations. + * We don't care about these operations anymore because we know this + * subtransaction will not commit. + */ + void + smgrAbortSubTransaction(void) + { + List *p; + + foreach (p, TransactionGetPendingDeletes()) + { + PendingRelDelete pending = lfirst(p); + + if (pending->atCommit == false) + smgr_internal_unlink(pending->relnode, + pending->which, + pending->isTemp, + false); + } + } + + /* + * smgrCommitSubTransaction() --- Take care of subtransaction commit. + * + * Reassign all items in the pending deletes list to the parent transaction. + */ + void + smgrCommitSubTransaction(void) + { + List *pending, + *parentPending; + + pending = TransactionGetPendingDeletes(); + parentPending = TransactionGetParentPendingDeletes(); + + TransactionSetParentPendingDeletes(nconc(parentPending, pending)); } /* *************** *** 599,609 **** { int nrels; RelFileNode *rptr; ! PendingRelDelete *pending; nrels = 0; ! for (pending = pendingDeletes; pending != NULL; pending = pending->next) { if (pending->atCommit == forCommit) nrels++; } --- 649,661 ---- { int nrels; RelFileNode *rptr; ! List *p; nrels = 0; ! foreach (p, TransactionGetPendingDeletes()) { + PendingRelDelete pending = lfirst(p); + if (pending->atCommit == forCommit) nrels++; } *************** *** 614,621 **** } rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode)); *ptr = rptr; ! for (pending = pendingDeletes; pending != NULL; pending = pending->next) { if (pending->atCommit == forCommit) *rptr++ = pending->relnode; } --- 666,675 ---- } rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode)); *ptr = rptr; ! foreach (p, TransactionGetPendingDeletes()) { + PendingRelDelete pending = lfirst(p); + if (pending->atCommit == forCommit) *rptr++ = pending->relnode; } diff -cr --exclude-from=diff-ignore 08simple/src/backend/utils/mmgr/portalmem.c 10smgr/src/backend/utils/mmgr/portalmem.c *** 08simple/src/backend/utils/mmgr/portalmem.c 2004-04-19 17:10:12.000000000 -0400 --- 10smgr/src/backend/utils/mmgr/portalmem.c 2004-04-25 12:47:46.014641484 -0400 *************** *** 511,513 **** --- 511,603 ---- PortalDrop(portal, true); } } + + #ifdef SUBTRANSACTIONS + /* + * Subtransaction commit handling for portals. + * + * Reassign all portals created by the current subtransaction to the + * parent transaction. + */ + void + AtSubCommit_Portals(TransactionId parentXid) + { + HASH_SEQ_STATUS status; + PortalHashEnt *hentry; + TransactionId curXid = GetCurrentTransactionId(); + + hash_seq_init(&status, PortalHashTable); + + while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) + { + Portal portal = hentry->portal; + + if (portal->createXact == curXid) + portal->createXact = parentXid; + } + } + + /* + * Subtransaction abort handling for portals. + * + * Deactivate all portals created during to the finishing subtransaction. + * Note that per AtSubCommit_Portals, this will catch portals created + * in descendents of the finishing subtransaction too. + */ + void + AtSubAbort_Portals(void) + { + HASH_SEQ_STATUS status; + PortalHashEnt *hentry; + TransactionId curXid = GetCurrentTransactionId(); + + hash_seq_init(&status, PortalHashTable); + + while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) + { + Portal portal = hentry->portal; + + if (portal->createXact != curXid) + continue; + + portal->portalActive = false; + if (PointerIsValid(portal->cleanup)) + { + (*portal->cleanup) (portal, true); + portal->cleanup = NULL; + } + } + } + + /* + * Subtransaction cleanup handling for portals. + * + * Drop all portals created in the aborting subtransaction and all + * its descendents. + */ + void + AtSubCleanup_Portals(void) + { + HASH_SEQ_STATUS status; + PortalHashEnt *hentry; + TransactionId curXid = GetCurrentTransactionId(); + + hash_seq_init(&status, PortalHashTable); + + while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) + { + Portal portal = hentry->portal; + + if (portal->createXact != curXid) + continue; + + /* + * Let's just make sure no one's active... + */ + portal->portalActive = false; + + /* Zap it with prejudice. */ + PortalDrop(portal, true); + } + } + #endif /* SUBTRANSACTIONS */ diff -cr --exclude-from=diff-ignore 08simple/src/include/access/xact.h 10smgr/src/include/access/xact.h *** 08simple/src/include/access/xact.h 2004-04-20 01:22:20.000000000 -0400 --- 10smgr/src/include/access/xact.h 2004-04-25 12:45:54.782938704 -0400 *************** *** 149,154 **** --- 149,158 ---- extern CommandId GetCurrentCommandId(void); extern AbsoluteTime GetCurrentTransactionStartTime(void); extern AbsoluteTime GetCurrentTransactionStartTimeUsec(int *usec); + extern List *TransactionGetPendingDeletes(void); + extern void TransactionSetPendingDeletes(List *); + extern List *TransactionGetParentPendingDeletes(void); + extern void TransactionSetParentPendingDeletes(List *); extern bool TransactionIdIsCurrentTransactionId(TransactionId xid); extern bool CommandIdIsCurrentCommandId(CommandId cid); extern void CommandCounterIncrement(void); diff -cr --exclude-from=diff-ignore 08simple/src/include/storage/smgr.h 10smgr/src/include/storage/smgr.h *** 08simple/src/include/storage/smgr.h 2004-04-19 17:10:13.000000000 -0400 --- 10smgr/src/include/storage/smgr.h 2004-04-25 12:37:33.222659985 -0400 *************** *** 61,66 **** --- 61,68 ---- extern BlockNumber smgrnblocks(SMgrRelation reln); extern BlockNumber smgrtruncate(SMgrRelation reln, BlockNumber nblocks); extern void smgrDoPendingDeletes(bool isCommit); + extern void smgrAbortSubTransaction(void); + extern void smgrCommitSubTransaction(void); extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr); extern void smgrcommit(void); extern void smgrabort(void); diff -cr --exclude-from=diff-ignore 08simple/src/include/utils/portal.h 10smgr/src/include/utils/portal.h *** 08simple/src/include/utils/portal.h 2004-04-19 17:10:13.000000000 -0400 --- 10smgr/src/include/utils/portal.h 2004-04-25 12:47:06.368113808 -0400 *************** *** 167,172 **** --- 167,177 ---- extern void AtCommit_Portals(void); extern void AtAbort_Portals(void); extern void AtCleanup_Portals(void); + #ifdef SUBTRANSACTIONS + extern void AtSubCommit_Portals(TransactionId); + extern void AtSubAbort_Portals(void); + extern void AtSubCleanup_Portals(void); + #endif /* SUBTRANSACTIONS */ extern Portal CreatePortal(const char *name, bool allowDup, bool dupSilent); extern Portal CreateNewPortal(void); extern void PortalDrop(Portal portal, bool isError);