head 1.29; access; symbols Version_2_1:1.12 old_buffer_manager:1.8 Version_2:1.5; locks; strict; comment @ * @; 1.29 date 92.08.18.18.27.16; author mer; state Exp; branches; next 1.28; 1.28 date 92.08.03.17.41.32; author mao; state Exp; branches; next 1.27; 1.27 date 92.05.28.23.08.29; author mer; state Exp; branches; next 1.26; 1.26 date 92.05.28.20.20.52; author mer; state Exp; branches; next 1.25; 1.25 date 92.03.25.17.29.15; author hong; state Exp; branches; next 1.24; 1.24 date 92.03.07.19.09.43; author hong; state Exp; branches; next 1.23; 1.23 date 92.02.25.21.49.11; author mer; state Exp; branches; next 1.22; 1.22 date 92.02.25.15.26.08; author clarsen; state Exp; branches; next 1.21; 1.21 date 91.08.15.17.10.03; author mao; state Exp; branches; next 1.20; 1.20 date 91.08.09.10.19.44; author mer; state Exp; branches; next 1.19; 1.19 date 91.08.06.19.38.45; author mao; state Exp; branches; next 1.18; 1.18 date 91.07.22.14.18.48; author mer; state Exp; branches; next 1.17; 1.17 date 91.05.26.23.09.59; author kemnitz; state Exp; branches; next 1.16; 1.16 date 91.05.23.18.15.29; author kemnitz; state Exp; branches; next 1.15; 1.15 date 91.05.07.15.59.21; author kemnitz; state Exp; branches; next 1.14; 1.14 date 91.05.01.11.26.32; author cimarron; state Exp; branches; next 1.13; 1.13 date 91.03.22.00.31.17; author mao; state Exp; branches; next 1.12; 1.12 date 91.02.19.10.05.13; author mao; state Exp; branches; next 1.11; 1.11 date 91.01.30.11.00.11; author hong; state Exp; branches; next 1.10; 1.10 date 91.01.25.22.10.49; author hong; state Exp; branches; next 1.9; 1.9 date 91.01.18.21.22.38; author hong; state Exp; branches; next 1.8; 1.8 date 90.09.21.11.58.11; author cimarron; state Exp; branches; next 1.7; 1.7 date 90.08.13.18.05.19; author cimarron; state Exp; branches; next 1.6; 1.6 date 90.08.08.16.10.36; author plai; state Exp; branches; next 1.5; 1.5 date 90.07.11.16.48.46; author mao; state Version_2; branches; next 1.4; 1.4 date 90.06.02.14.16.38; author cimarron; state Exp; branches; next 1.3; 1.3 date 90.05.16.13.56.02; author cimarron; state Exp; branches; next 1.2; 1.2 date 90.03.31.18.50.56; author cimarron; state Exp; branches; next 1.1; 1.1 date 90.03.26.20.32.39; author cimarron; state Exp; branches; next ; desc @redesigned V1 transaction system @ 1.29 log @changes to close all user defined portals on eoxact @ text @/* ---------------------------------------------------------------- * FILE * xact.c * * DESCRIPTION * top level transaction system support routines * * INTERFACE ROUTINES * StartTransactionCommand * CommitTransactionCommand * AbortCurrentTransaction * * StartTransactionBlock * CommitTransactionBlock * AbortTransactionBlock * * SlaveStartTransaction * SlaveCommitTransaction * SlaveAbortTransaction * * NEW CODE * * UserAbortTransactionBlock * * Transaction aborts can now occur two ways: * * 1) system dies from some internal cause (Assert, etc..) * 2) user types abort * * These two cases used to be treated identically, but now * we need to distinguish them. Why? consider the following * two situatuons: * * case 1 case 2 * ------ ------ * 1) user types BEGIN 1) user types BEGIN * 2) user does something 2) user does something * 3) user does not like what 3) system aborts for some reason * she shes and types ABORT * * In case 1, we want to abort the transaction and return to the * default state. In case 2, there may be more commands coming * our way which are part of the same transaction block and we have * to ignore these commands until we see an END transaction. * * Internal aborts are now handled by AbortTransactionBlock(), just as * they always have been, and user aborts are now handled by * UserAbortTransactionBlock(). Both of them rely on AbortTransaction() * to do all the real work. The only difference is what state we * enter after AbortTransaction() does it's work: * * * AbortTransactionBlock() leaves us in TBLOCK_ABORT and * * UserAbortTransactionBlock() leaves us in TBLOCK_ENDABORT * * NOTES * This file is an attempt at a redesign of the upper layer * of the V1 transaction system which was too poorly thought * out to describe. This new system hopes to be both simpler * in design, simpler to extend and needs to contain added * functionality to solve problems beyond the scope of the V1 * system. (In particuler, communication of transaction * information between parallel backends has to be supported) * * The essential aspects of the transaction system are: * * o transaction id generation * o transaction log updating * o memory cleanup * o cache invalidation * o lock cleanup * * Hence, the functional division of the transaction code is * based on what of the above things need to be done during * a start/commit/abort transaction. For instance, the * routine AtCommit_Memory() takes care of all the memory * cleanup stuff done at commit time. * * The code is layered as follows: * * StartTransaction * CommitTransaction * AbortTransaction * UserAbortTransaction * * are provided to do the lower level work like recording * the transaction status in the log and doing memory cleanup. * above these routines are another set of functions: * * StartTransactionCommand * CommitTransactionCommand * AbortCurrentTransaction * * These are the routines used in the postgres main processing * loop. They are sensitive to the current transaction block state * and make calls to the lower level routines appropriately. * * Support for transaction blocks is provided via the functions: * * StartTransactionBlock * CommitTransactionBlock * AbortTransactionBlock * * These are invoked only in responce to a user "BEGIN", "END", * or "ABORT" command. The tricky part about these functions * is that they are called within the postgres main loop, in between * the StartTransactionCommand() and CommitTransactionCommand(). * * For example, consider the following sequence of user commands: * * 1) begin * 2) retrieve (foo.all) * 3) append foo (bar = baz) * 4) end * * in the main processing loop, this results in the following * transaction sequence: * * / StartTransactionCommand(); * 1) / ProcessUtility(); << begin * \ StartTransactionBlock(); * \ CommitTransactionCommand(); * * / StartTransactionCommand(); * 2) < ProcessQuery(); << retrieve (foo.all) * \ CommitTransactionCommand(); * * / StartTransactionCommand(); * 3) < ProcessQuery(); << append foo (bar = baz) * \ CommitTransactionCommand(); * * / StartTransactionCommand(); * 4) / ProcessUtility(); << end * \ CommitTransactionBlock(); * \ CommitTransactionCommand(); * * The point of this example is to demonstrate the need for * StartTransactionCommand() and CommitTransactionCommand() to * be state smart -- they should do nothing in between the calls * to StartTransactionBlock() and EndTransactionBlock() and * outside these calls they need to do normal start/commit * processing. * * Furthermore, suppose the "retrieve (foo.all)" caused an abort * condition. We would then want to abort the transaction and * ignore all subsequent commands up to the "end". * -cim 3/23/90 * * The "slave" transction routines are used within the parallel * slave ackends. * * SlaveStartTransaction * SlaveCommitTransaction * SlaveAbortTransaction * * Since slave backends do none of the log or transaction state * processing, these routines only preform cache, lock table * and memory initialization/cleanup duties needed by the rest * of the system. * * IDENTIFICATION * $Header: /private/mer/pg/src/access/transam/RCS/xact.c,v 1.28 1992/08/03 17:41:32 mao Exp mer $ * ---------------------------------------------------------------- */ #include "tmp/postgres.h" #include "access/xact.h" RcsId("$Header: /private/mer/pg/src/access/transam/RCS/xact.c,v 1.28 1992/08/03 17:41:32 mao Exp mer $"); /* ---------------- * global variables holding the current transaction state. * * Note: when we are running several slave processes, the * current transaction state data is copied into shared memory * and the CurrentTransactionState pointer changed to * point to the shared copy. All this occurrs in slaves.c * ---------------- */ TransactionStateData CurrentTransactionStateData = { 0, /* transaction id */ FirstCommandId, /* command id */ 0x0, /* start time */ TRANS_DEFAULT, /* transaction state */ TBLOCK_DEFAULT /* transaction block state */ }; TransactionState CurrentTransactionState = &CurrentTransactionStateData; /* ---------------- * slave-local transaction state. This is only used by * the parallel slave backend transaction code. * ---------------- */ bool inSlaveTransaction = false; /* ---------------- * info returned when the system is desabled * * Note: I have no idea what the significance of the * 1073741823 in DisabledStartTime.. I just carried * this over when converting things from the old * V1 transaction system. -cim 3/18/90 * ---------------- */ TransactionId DisabledTransactionId = (TransactionId)-1; CommandId DisabledCommandId = (CommandId) -1; Time DisabledStartTime = (Time) 1073741823; /* ---------------- * overflow flag * ---------------- */ bool CommandIdCounterOverflowFlag; /* ---------------- * catalog creation transaction bootstrapping flag. * This should be eliminated and added to the transaction * state stuff. -cim 3/19/90 * ---------------- */ bool AMI_OVERRIDE = false; /* ---------------------------------------------------------------- * transaction state accessors * ---------------------------------------------------------------- */ /* -------------------------------- * TranactionFlushEnabled() * SetTranactionFlushEnabled() * * These are used to test and set the "TransactionFlushState" * varable. If this variable is true (the default), then * the system will flush all dirty buffers to disk at the end * of each transaction. If false then we are assuming the * buffer pool resides in stable main memory, in which case we * only do writes as necessary. * -------------------------------- */ int TransactionFlushState = 1; int TransactionFlushEnabled() { return TransactionFlushState; } void SetTransactionFlushEnabled(state) bool state; { TransactionFlushState = (state == true); } /* -------------------------------- * IsTransactionState * * This returns true if we are currently running a query * within an executing transaction. * -------------------------------- */ bool IsTransactionState() { TransactionState s = CurrentTransactionState; switch (s->state) { case TRANS_DEFAULT: return false; case TRANS_START: return true; case TRANS_INPROGRESS: return true; case TRANS_COMMIT: return true; case TRANS_ABORT: return true; case TRANS_DISABLED: return false; } /* * Shouldn't get here, but lint is not happy with this... */ return(false); } /* -------------------------------- * IsAbortedTransactionBlockState * * This returns true if we are currently running a query * within an aborted transaction block. * -------------------------------- */ bool IsAbortedTransactionBlockState() { TransactionState s = CurrentTransactionState; if (s->blockState == TBLOCK_ABORT) return true; return false; } /* -------------------------------- * OverrideTransactionSystem * * This is used to temporarily disable the transaction * processing system in order to do initialization of * the transaction system data structures and relations * themselves. * -------------------------------- */ int SavedTransactionState; void OverrideTransactionSystem(flag) bool flag; { TransactionState s = CurrentTransactionState; if (flag == true) { if (s->state == TRANS_DISABLED) return; SavedTransactionState = s->state; s->state = TRANS_DISABLED; } else { if (s->state != TRANS_DISABLED) return; s->state = SavedTransactionState; } } /* -------------------------------- * GetCurrentTransactionId * * This returns the id of the current transaction, or * the id of the "disabled" transaction. * -------------------------------- */ TransactionId GetCurrentTransactionId() { TransactionState s = CurrentTransactionState; /* ---------------- * if the transaction system is disabled, we return * the special "disabled" transaction id. * ---------------- */ if (s->state == TRANS_DISABLED) return (TransactionId) DisabledTransactionId; /* ---------------- * otherwise return the current transaction id. * ---------------- */ return (TransactionId) s->transactionIdData; } /* -------------------------------- * GetCurrentCommandId * -------------------------------- */ CommandId GetCurrentCommandId() { TransactionState s = CurrentTransactionState; /* ---------------- * if the transaction system is disabled, we return * the special "disabled" command id. * ---------------- */ if (s->state == TRANS_DISABLED) return (CommandId) DisabledCommandId; return s->commandId; } /* -------------------------------- * GetCurrentTransactionStartTime * -------------------------------- */ Time GetCurrentTransactionStartTime() { TransactionState s = CurrentTransactionState; /* ---------------- * if the transaction system is disabled, we return * the special "disabled" starting time. * ---------------- */ if (s->state == TRANS_DISABLED) return (Time) DisabledStartTime; return s->startTime; } /* -------------------------------- * TransactionIdIsCurrentTransactionId * -------------------------------- */ bool TransactionIdIsCurrentTransactionId(xid) TransactionId xid; { TransactionState s = CurrentTransactionState; if (AMI_OVERRIDE) return false; return (bool) TransactionIdEquals(xid, s->transactionIdData); } /* -------------------------------- * CommandIdIsCurrentCommandId * -------------------------------- */ bool CommandIdIsCurrentCommandId(cid) CommandId cid; { TransactionState s = CurrentTransactionState; if (AMI_OVERRIDE) return false; return (cid == s->commandId) ? true : false; } /* -------------------------------- * ClearCommandIdCounterOverflowFlag * -------------------------------- */ void ClearCommandIdCounterOverflowFlag() { CommandIdCounterOverflowFlag = false; } /* -------------------------------- * CommandCounterIncrement * -------------------------------- */ void CommandCounterIncrement() { CurrentTransactionStateData.commandId += 1; if (CurrentTransactionStateData.commandId == FirstCommandId) { CommandIdCounterOverflowFlag = true; elog(WARN, "You may only have 65535 commands per transaction"); } /* make cache changes visible to me */ AtCommit_Cache(); AtStart_Cache(); } /* ---------------------------------------------------------------- * initialization stuff * ---------------------------------------------------------------- */ void InitializeTransactionSystem() { InitializeTransactionLog(); } /* ---------------------------------------------------------------- * StartTransaction stuff * ---------------------------------------------------------------- */ /* -------------------------------- * AtStart_Cache * -------------------------------- */ void AtStart_Cache() { DiscardInvalid(); } /* -------------------------------- * AtStart_Locks * -------------------------------- */ void AtStart_Locks() { /* * at present, it is unknown to me what belongs here -cim 3/18/90 * * There isn't anything to do at the start of a xact for locks. * -mer 5/24/92 */ } /* -------------------------------- * AtStart_Memory * -------------------------------- */ void AtStart_Memory() { Portal portal; MemoryContext portalContext; /* ---------------- * get the blank portal and its memory context * ---------------- */ portal = GetPortalByName(NULL); portalContext = (MemoryContext) PortalGetHeapMemory(portal); /* ---------------- * tell system to allocate in the blank portal context * ---------------- */ (void) MemoryContextSwitchTo(portalContext); StartPortalAllocMode(DefaultAllocMode, 0); } /* ---------------------------------------------------------------- * CommitTransaction stuff * ---------------------------------------------------------------- */ /* -------------------------------- * RecordTransactionCommit * * Note: the two calls to BufferManagerFlush() exist to ensure * that data pages are written before log pages. These * explicit calls should be replaced by a more efficient * ordered page write scheme in the buffer manager * -cim 3/18/90 * -------------------------------- */ void RecordTransactionCommit() { TransactionId xid; int leak; /* ---------------- * get the current transaction id * ---------------- */ xid = GetCurrentTransactionId(); /* ---------------- * flush the buffer manager pages. Note: if we have stable * main memory, dirty shared buffers are not flushed * plai 8/7/90 * ---------------- */ leak = BufferPoolCheckLeak(); FlushBufferPool(!TransactionFlushEnabled()); if (leak) ResetBufferPool(); /* ---------------- * have the transaction access methods record the status * of this transaction id in the pg_log / pg_time relations. * ---------------- */ TransactionIdCommit(xid); /* ---------------- * Now write the log/time info to the disk too. * ---------------- */ leak = BufferPoolCheckLeak(); FlushBufferPool(!TransactionFlushEnabled()); if (leak) ResetBufferPool(); } /* -------------------------------- * AtCommit_Cache * -------------------------------- */ void AtCommit_Cache() { /* ---------------- * Make catalog changes visible to me for the next command. * Other backends will not process my invalidation messages until * after I commit and free my locks--though they will do * unnecessary work if I abort. * ---------------- */ RegisterInvalid(true); } /* -------------------------------- * AtCommit_Locks * -------------------------------- */ void AtCommit_Locks() { /* ---------------- * XXX What if ProcReleaseLocks fails? (race condition?) * * Then you're up a creek! -mer 5/24/92 * ---------------- */ ProcReleaseLocks(); } /* -------------------------------- * AtCommit_Memory * -------------------------------- */ void AtCommit_Memory() { /* ---------------- * now that we're "out" of a transaction, have the * system allocate things in the top memory context instead * of the blank portal memory context. * ---------------- */ EndPortalAllocMode(); (void) MemoryContextSwitchTo(TopMemoryContext); } /* ---------------------------------------------------------------- * AbortTransaction stuff * ---------------------------------------------------------------- */ /* -------------------------------- * RecordTransactionAbort * -------------------------------- */ void RecordTransactionAbort() { TransactionId xid; /* ---------------- * get the current transaction id * ---------------- */ xid = GetCurrentTransactionId(); /* ---------------- * have the transaction access methods record the status * of this transaction id in the pg_log / pg_time relations. * ---------------- */ TransactionIdAbort(xid); /* ---------------- * flush the buffer manager pages. Note: if we have stable * main memory, dirty shared buffers are not flushed * plai 8/7/90 * ---------------- */ ResetBufferPool(!TransactionFlushEnabled()); } /* -------------------------------- * AtAbort_Cache * -------------------------------- */ void AtAbort_Cache() { RegisterInvalid(false); } /* -------------------------------- * AtAbort_Locks * -------------------------------- */ void AtAbort_Locks() { /* ---------------- * XXX What if ProcReleaseLocks() fails? (race condition?) * * Then you're up a creek without a paddle! -mer * ---------------- */ ProcReleaseLocks(); } /* -------------------------------- * AtAbort_Memory * -------------------------------- */ void AtAbort_Memory() { /* ---------------- * after doing an abort transaction, make certain the * system uses the top memory context rather then the * portal memory context (until the next transaction). * ---------------- */ (void) MemoryContextSwitchTo(TopMemoryContext); } /* ---------------------------------------------------------------- * interface routines * ---------------------------------------------------------------- */ /* -------------------------------- * StartTransaction * * -------------------------------- */ void StartTransaction() { TransactionState s = CurrentTransactionState; extern bool TransactionInitWasProcessed; /* XXX style */ /* ---------------- * Check the current transaction state. If the transaction system * is switched off, or if we're already in a transaction, do nothing. * We're already in a transaction when the monitor sends a null * command to the backend to flush the comm channel. This is a * hacky fix to a communications problem, and we keep having to * deal with it here. We should fix the comm channel code. mao 080891 * ---------------- */ if (s->state == TRANS_DISABLED || s->state == TRANS_INPROGRESS) return; /* ---------------- * set the current transaction state information * appropriately during start processing * ---------------- */ s->state = TRANS_START; /* ---------------- * generate a new transaction id * ---------------- */ GetNewTransactionId(&(s->transactionIdData)); /* ---------------- * initialize current transaction state fields * ---------------- */ s->commandId = FirstCommandId; s->startTime = GetCurrentTime(); /* ---------------- * initialize the various transaction subsystems * ---------------- */ AtStart_Cache(); AtStart_Locks(); AtStart_Memory(); /* ---------------- * done with start processing, set current transaction * state to "in progress" * ---------------- */ s->state = TRANS_INPROGRESS; } /* --------------- * Tell me if we are currently in progress * --------------- */ bool CurrentXactInProgress() { return (CurrentTransactionState->state == TRANS_INPROGRESS); } /* -------------------------------- * CommitTransaction * * -------------------------------- */ void CommitTransaction() { TransactionState s = CurrentTransactionState; /* ---------------- * check the current transaction state * ---------------- */ if (s->state == TRANS_DISABLED) return; if (s->state != TRANS_INPROGRESS) elog(NOTICE, "CommitTransaction and not in in-progress state "); /* ---------------- * set the current transaction state information * appropriately during the abort processing * ---------------- */ s->state = TRANS_COMMIT; /* ---------------- * do commit processing * ---------------- */ AtEOXact_portals(); RecordTransactionCommit(); AtCommit_LocalRels(); AtCommit_Cache(); AtCommit_Locks(); AtCommit_Memory(); /* ---------------- * done with commit processing, set current transaction * state back to default * ---------------- */ s->state = TRANS_DEFAULT; { /* want this after commit */ extern void Async_NotifyAtCommit(); if (IsNormalProcessingMode()) Async_NotifyAtCommit(); } } /* -------------------------------- * AbortTransaction * * -------------------------------- */ void AbortTransaction() { TransactionState s = CurrentTransactionState; /* ---------------- * check the current transaction state * ---------------- */ if (s->state == TRANS_DISABLED) return; if (s->state != TRANS_INPROGRESS) elog(NOTICE, "AbortTransaction and not in in-progress state "); /* ---------------- * set the current transaction state information * appropriately during the abort processing * ---------------- */ s->state = TRANS_ABORT; /* ---------------- * do abort processing * ---------------- */ AtEOXact_portals(); RecordTransactionAbort(); AtAbort_LocalRels(); AtAbort_Cache(); AtAbort_Locks(); AtAbort_Memory(); /* ---------------- * done with abort processing, set current transaction * state back to default * ---------------- */ s->state = TRANS_DEFAULT; } /* ---------------------------------------------------------------- * slave backend transaction interface * * These functions take care of doing the proper transaction * processing when we are running inside a slave backend. * * Since the master backend calls StartTransactionCommand(), * CommitTransactionCommand() and AbortCurrentTransaction(), * it ends up doing all the real work. * * The slaves only have to do cache, lock table and memory * cleanup to support the parts of the system which don't * understand parallel processing. Slaves don't touch the * log or the transaction state because the master backend * does this. The slave-local transaction state is updated. * ---------------------------------------------------------------- */ /* -------------------------------- * SlaveStartTransaction * * -------------------------------- */ void SlaveStartTransaction() { AtStart_Cache(); AtStart_Locks(); AtStart_Memory(); inSlaveTransaction = true; } /* -------------------------------- * SlaveCommitTransaction * * -------------------------------- */ void SlaveCommitTransaction() { AtCommit_LocalRels(); AtCommit_Cache(); AtCommit_Locks(); AtCommit_Memory(); inSlaveTransaction = false; } /* -------------------------------- * SlaveAbortTransaction * * Note: Since AtAbort_Memory does no memory cleanup, we * call AtCommit_Memory instead. * -------------------------------- */ void SlaveAbortTransaction() { AtAbort_LocalRels(); AtAbort_Cache(); AtAbort_Locks(); AtCommit_Memory(); inSlaveTransaction = false; } /* -------------------------------- * InSlaveTransaction * * returns 1 if we are "in" a slave transaction. This * is used by the slave abort code to determine if we don't * need to do abort cleanup in the slaves. * -------------------------------- */ int InSlaveTransaction() { return (inSlaveTransaction == true); } /* ---------------------------------------------------------------- * transaction system interface functions. these provide * support for transaction blocks above the start / abort / * commit transaction routines above. * ---------------------------------------------------------------- */ /* -------------------------------- * StartTransactionCommand * -------------------------------- */ void StartTransactionCommand() { TransactionState s = CurrentTransactionState; switch(s->blockState) { /* ---------------- * if we aren't in a transaction block, we * just do our usual start transaction. * ---------------- */ case TBLOCK_DEFAULT: StartTransaction(); break; /* ---------------- * We should never experience this -- if we do it * means the BEGIN state was not changed in the previous * CommitTransactionCommand(). If we get it, we print * a warning and change to the in-progress state. * ---------------- */ case TBLOCK_BEGIN: elog(NOTICE, "StartTransactionCommand: unexpected TBLOCK_BEGIN"); s->blockState = TBLOCK_INPROGRESS; break; /* ---------------- * This is the case when are somewhere in a transaction * block and about to start a new command. For now we * do nothing but someday we may do command-local resource * initialization. * ---------------- */ case TBLOCK_INPROGRESS: break; /* ---------------- * As with BEGIN, we should never experience this -- * if we do it means the END state was not changed in the * previous CommitTransactionCommand(). If we get it, we * print a warning, commit the transaction, start a new * transaction and change to the default state. * ---------------- */ case TBLOCK_END: elog(NOTICE, "StartTransactionCommand: unexpected TBLOCK_END"); s->blockState = TBLOCK_DEFAULT; CommitTransaction(); StartTransaction(); break; /* ---------------- * Here we are in the middle of a transaction block but * one of the commands caused an abort so we do nothing * but remain in the abort state. Eventually we will get * to the "END TRANSACTION" which will set things straight. * ---------------- */ case TBLOCK_ABORT: break; /* ---------------- * This means we somehow aborted and the last call to * CommitTransactionCommand() didn't clear the state so * we remain in the ENDABORT state and mabey next time * we get to CommitTransactionCommand() the state will * get reset to default. * ---------------- */ case TBLOCK_ENDABORT: elog(NOTICE, "StartTransactionCommand: unexpected TBLOCK_ENDABORT"); break; } } /* -------------------------------- * CommitTransactionCommand * -------------------------------- */ void CommitTransactionCommand() { TransactionState s = CurrentTransactionState; switch(s->blockState) { /* ---------------- * if we aren't in a transaction block, we * just do our usual transaction commit * ---------------- */ case TBLOCK_DEFAULT: CommitTransaction(); break; /* ---------------- * This is the case right after we get a "BEGIN TRANSACTION" * command, but the user hasn't done anything else yet, so * we change to the "transaction block in progress" state * and return. * ---------------- */ case TBLOCK_BEGIN: s->blockState = TBLOCK_INPROGRESS; break; /* ---------------- * This is the case when we have finished executing a command * someplace within a transaction block. We increment the * command counter and return. Someday we may free resources * local to the command. * ---------------- */ case TBLOCK_INPROGRESS: CommandCounterIncrement(); break; /* ---------------- * This is the case when we just got the "END TRANSACTION" * statement, so we go back to the default state and * commit the transaction. * ---------------- */ case TBLOCK_END: s->blockState = TBLOCK_DEFAULT; CommitTransaction(); break; /* ---------------- * Here we are in the middle of a transaction block but * one of the commands caused an abort so we do nothing * but remain in the abort state. Eventually we will get * to the "END TRANSACTION" which will set things straight. * ---------------- */ case TBLOCK_ABORT: break; /* ---------------- * Here we were in an aborted transaction block which * just processed the "END TRANSACTION" command from the * user, so now we return the to default state. * ---------------- */ case TBLOCK_ENDABORT: s->blockState = TBLOCK_DEFAULT; break; } } /* -------------------------------- * AbortCurrentTransaction * -------------------------------- */ void AbortCurrentTransaction() { TransactionState s = CurrentTransactionState; switch(s->blockState) { /* ---------------- * if we aren't in a transaction block, we * just do our usual abort transaction. * ---------------- */ case TBLOCK_DEFAULT: AbortTransaction(); break; /* ---------------- * If we are in the TBLOCK_BEGIN it means something * screwed up right after reading "BEGIN TRANSACTION" * so we enter the abort state. Eventually an "END * TRANSACTION" will fix things. * ---------------- */ case TBLOCK_BEGIN: s->blockState = TBLOCK_ABORT; AbortTransaction(); break; /* ---------------- * This is the case when are somewhere in a transaction * block which aborted so we abort the transaction and * set the ABORT state. Eventually an "END TRANSACTION" * will fix things and restore us to a normal state. * ---------------- */ case TBLOCK_INPROGRESS: s->blockState = TBLOCK_ABORT; AbortTransaction(); break; /* ---------------- * Here, the system was fouled up just after the * user wanted to end the transaction block so we * abort the transaction and put us back into the * default state. * ---------------- */ case TBLOCK_END: s->blockState = TBLOCK_DEFAULT; AbortTransaction(); break; /* ---------------- * Here, we are already in an aborted transaction * state and are waiting for an "END TRANSACTION" to * come along and lo and behold, we abort again! * So we just remain in the abort state. * ---------------- */ case TBLOCK_ABORT: break; /* ---------------- * Here we were in an aborted transaction block which * just processed the "END TRANSACTION" command but somehow * aborted again.. since we must have done the abort * processing, we return to the default state. * ---------------- */ case TBLOCK_ENDABORT: s->blockState = TBLOCK_DEFAULT; break; } } /* ---------------------------------------------------------------- * transaction block support * ---------------------------------------------------------------- */ /* -------------------------------- * BeginTransactionBlock * -------------------------------- */ void BeginTransactionBlock() { TransactionState s = CurrentTransactionState; /* ---------------- * check the current transaction state * ---------------- */ if (s->state == TRANS_DISABLED) return; if (s->blockState != TBLOCK_DEFAULT) elog(NOTICE, "BeginTransactionBlock and not in default state "); /* ---------------- * set the current transaction block state information * appropriately during begin processing * ---------------- */ s->blockState = TBLOCK_BEGIN; /* ---------------- * do begin processing * ---------------- */ /* ---------------- * done with begin processing, set block state to inprogress * ---------------- */ s->blockState = TBLOCK_INPROGRESS; } /* -------------------------------- * EndTransactionBlock * -------------------------------- */ void EndTransactionBlock() { TransactionState s = CurrentTransactionState; /* ---------------- * check the current transaction state * ---------------- */ if (s->state == TRANS_DISABLED) return; if (s->blockState == TBLOCK_INPROGRESS) { /* ---------------- * here we are in a transaction block which should commit * when we get to the upcoming CommitTransactionCommand() * so we set the state to "END". CommitTransactionCommand() * will recognize this and commit the transaction and return * us to the default state * ---------------- */ s->blockState = TBLOCK_END; return; } if (s->blockState == TBLOCK_ABORT) { /* ---------------- * here, we are in a transaction block which aborted * and since the AbortTransaction() was already done, * we do whatever is needed and change to the special * "END ABORT" state. The upcoming CommitTransactionCommand() * will recognise this and then put us back in the default * state. * ---------------- */ s->blockState = TBLOCK_ENDABORT; return; } /* ---------------- * We should not get here, but if we do, we go to the ENDABORT * state after printing a warning. The upcoming call to * CommitTransactionCommand() will then put us back into the * default state. * ---------------- */ elog(NOTICE, "EndTransactionBlock and not inprogress/abort state "); s->blockState = TBLOCK_ENDABORT; } /* -------------------------------- * AbortTransactionBlock * -------------------------------- */ void AbortTransactionBlock() { TransactionState s = CurrentTransactionState; /* ---------------- * check the current transaction state * ---------------- */ if (s->state == TRANS_DISABLED) return; if (s->blockState == TBLOCK_INPROGRESS) { /* ---------------- * here we were inside a transaction block something * screwed up inside the system so we enter the abort state, * do the abort processing and then return. * We remain in the abort state until we see the upcoming * END TRANSACTION command. * ---------------- */ s->blockState = TBLOCK_ABORT; /* ---------------- * do abort processing and return * ---------------- */ AbortTransaction(); return; } /* ---------------- * this case should not be possible, because it would mean * the user entered an "abort" from outside a transaction block. * So we print an error message, abort the transaction and * enter the "ENDABORT" state so we will end up in the default * state after the upcoming CommitTransactionCommand(). * ---------------- */ elog(NOTICE, "AbortTransactionBlock and not inprogress state"); AbortTransaction(); s->blockState = TBLOCK_ENDABORT; } /* -------------------------------- * UserAbortTransactionBlock * -------------------------------- */ void UserAbortTransactionBlock() { TransactionState s = CurrentTransactionState; /* ---------------- * check the current transaction state * ---------------- */ if (s->state == TRANS_DISABLED) return; if (s->blockState == TBLOCK_INPROGRESS) { /* ---------------- * here we were inside a transaction block and we * got an abort command from the user, so we move to * the abort state, do the abort processing and * then change to the ENDABORT state so we will end up * in the default state after the upcoming * CommitTransactionCommand(). * ---------------- */ s->blockState = TBLOCK_ABORT; /* ---------------- * do abort processing * ---------------- */ AbortTransaction(); /* ---------------- * change to the end abort state and return * ---------------- */ s->blockState = TBLOCK_ENDABORT; return; } /* ---------------- * this case should not be possible, because it would mean * the user entered an "abort" from outside a transaction block. * So we print an error message, abort the transaction and * enter the "ENDABORT" state so we will end up in the default * state after the upcoming CommitTransactionCommand(). * ---------------- */ elog(NOTICE, "UserAbortTransactionBlock and not inprogress state"); AbortTransaction(); s->blockState = TBLOCK_ENDABORT; } bool IsTransactionBlock() { TransactionState s = CurrentTransactionState; if (s->blockState == TBLOCK_INPROGRESS || s->blockState == TBLOCK_ENDABORT) { return (true); } return (false); } @ 1.28 log @minor cleanup @ text @d160 1 a160 1 * $Header: /private/mao/postgres/src/access/transam/RCS/xact.c,v 1.27 1992/05/28 23:08:29 mer Exp $ d167 1 a167 1 RcsId("$Header: /private/mao/postgres/src/access/transam/RCS/xact.c,v 1.27 1992/05/28 23:08:29 mer Exp $"); d824 1 d875 1 @ 1.27 log @give a warning when the command counter has overflowed @ text @d160 1 a160 1 * $Header: /private/mer/pg.latest/src/access/transam/RCS/xact.c,v 1.26 1992/05/28 20:20:52 mer Exp mer $ d167 1 a167 1 RcsId("$Header: /private/mer/pg.latest/src/access/transam/RCS/xact.c,v 1.26 1992/05/28 20:20:52 mer Exp mer $"); d746 1 a746 12 /* * ------------- * XXX: mao commented these lines out 20 feb 91. due to fe/be comm problems, * we get this message for every query submitted to the monitor. i just * want the message to go away. we should fix the comm problems instead. * ------------- * * if (s->state != TRANS_DEFAULT) * elog(NOTICE, "StartTransaction and not in default state"); */ d825 1 a825 1 AtCommit_LocalRels(); @ 1.26 log @Transaction ids are now longs and command ids are now shorts @ text @d160 1 a160 1 * $Header: /private/mer/pg.latest/src/access/transam/RCS/xact.c,v 1.25 1992/03/25 17:29:15 hong Exp mer $ d167 1 a167 1 RcsId("$Header: /private/mer/pg.latest/src/access/transam/RCS/xact.c,v 1.25 1992/03/25 17:29:15 hong Exp mer $"); d461 1 @ 1.25 log @plugged more buffer leaks @ text @d160 1 a160 1 * $Header: access/transam/RCS/xact.c,v 1.24 92/03/07 19:09:43 hong Exp Locker: hong $ d167 1 a167 1 RcsId("$Header: access/transam/RCS/xact.c,v 1.24 92/03/07 19:09:43 hong Exp Locker: hong $"); d179 1 a179 1 { 0 }, /* transaction id data */ d205 1 a205 3 TransactionIdData DisabledTransactionIdData = { '\177', '\177', '\177', '\177', '\177' }; d208 1 a208 1 (CommandId) '\177'; d352 1 a352 1 return (TransactionId) &DisabledTransactionIdData; d358 1 a358 1 return (TransactionId) &(s->transactionIdData); d418 1 a418 1 TransactionIdEquals(xid, &(s->transactionIdData)); d436 1 a436 1 (AsUint8(cid) == AsUint8(s->commandId)) ? true : false; d501 6 a506 1 /* at present, it is unknown to me what belongs here -cim 3/18/90 */ a612 8 TransactionId xid; /* ---------------- * get the current transaction id * ---------------- */ xid = GetCurrentTransactionId(); d615 2 a691 8 TransactionId xid; /* ---------------- * get the current transaction id * ---------------- */ xid = GetCurrentTransactionId(); d694 2 @ 1.24 log @cleaned up buffer flush interface @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.23 92/02/25 21:49:11 mer Exp Locker: hong $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.23 92/02/25 21:49:11 mer Exp Locker: hong $"); d551 1 d565 1 a565 1 BufferPoolCheckLeak(); d567 1 d580 1 a580 1 BufferPoolCheckLeak(); d582 1 @ 1.23 log @add routine to determine if current Xact is in progress @ text @d160 1 a160 1 * $Header: /u/mer/pg/src/access/transam/RCS/xact.c,v 1.22 1992/02/25 15:26:08 clarsen Exp mer $ d167 1 a167 1 RcsId("$Header: /u/mer/pg/src/access/transam/RCS/xact.c,v 1.22 1992/02/25 15:26:08 clarsen Exp mer $"); d564 2 a565 1 BufferManagerFlush(!TransactionFlushEnabled()); d578 2 a579 1 BufferManagerFlush(!TransactionFlushEnabled()); d672 1 a672 1 BufferManagerFlush(!TransactionFlushEnabled()); @ 1.22 log @add async notification at end of commite @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.21 91/08/15 17:10:03 mao Exp Locker: clarsen $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.21 91/08/15 17:10:03 mao Exp Locker: clarsen $"); d795 10 @ 1.21 log @new routine to determine whether or not we're inside a transaction block. used by parser/gram.y to disallow portals outside of xact blocks. @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.20 91/08/09 10:19:44 mer Exp Locker: mao $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.20 91/08/09 10:19:44 mer Exp Locker: mao $"); d840 5 @ 1.20 log @fix for null command from monitor. @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.19 91/08/06 19:38:45 mao Exp $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.19 91/08/06 19:38:45 mao Exp $"); d1403 13 @ 1.19 log @CommandCounterIncrement needs to invalidate the cache, not just promise to. @ text @d160 1 a160 1 * $Header: /users/mao/postgres/src/access/transam/RCS/xact.c,v 1.18 1991/07/22 14:18:48 mer Exp $ d167 1 a167 1 RcsId("$Header: /users/mao/postgres/src/access/transam/RCS/xact.c,v 1.18 1991/07/22 14:18:48 mer Exp $"); d739 6 a744 1 * check the current transaction state d747 1 a747 1 if (s->state == TRANS_DISABLED) @ 1.18 log @function calls for new lock manager. @ text @d160 1 a160 1 * $Header: access/transam/RCS/xact.c,v 1.17 91/05/26 23:09:59 kemnitz Exp Locker: mer $ d167 1 a167 1 RcsId("$Header: access/transam/RCS/xact.c,v 1.17 91/05/26 23:09:59 kemnitz Exp Locker: mer $"); d467 1 @ 1.17 log @added code to clean up after the temp relation heap am's. @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.16 91/05/23 18:15:29 kemnitz Exp Locker: kemnitz $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.16 91/05/23 18:15:29 kemnitz Exp Locker: kemnitz $"); d613 1 a613 1 * XXX What if LMLockReleaseAll fails? (race condition?) d616 1 a616 2 LMLockReleaseAll(PageLockTableId, xid); LMLockReleaseAll(MultiLevelLockTableId, xid); d698 1 a698 1 * XXX What if LMLockReleaseAll fails? (race condition?) d701 1 a701 2 LMLockReleaseAll(PageLockTableId, xid); LMLockReleaseAll(MultiLevelLockTableId, xid); @ 1.16 log @got rid of has return(e); and return; @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.15 91/05/07 15:59:21 kemnitz Exp Locker: kemnitz $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.15 91/05/07 15:59:21 kemnitz Exp Locker: kemnitz $"); d825 1 d870 1 d924 1 d942 1 @ 1.15 log @fixed include file problem @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.14 91/05/01 11:26:32 cimarron Exp Locker: kemnitz $ d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.14 91/05/01 11:26:32 cimarron Exp Locker: kemnitz $"); d281 4 @ 1.14 log @transaction system now distinguished between user aborts and internal aborts @ text @d160 1 a160 1 * $Header: RCS/xact.c,v 1.13 91/03/22 00:31:17 mao Exp Locker: cimarron $ d164 1 d167 1 a167 1 RcsId("$Header: RCS/xact.c,v 1.13 91/03/22 00:31:17 mao Exp Locker: cimarron $"); @ 1.13 log @when we increment the command counter, flush the caches so that we can see the results of the command we just completed. @ text @d21 33 d82 1 d160 1 a160 1 * $Header: RCS/xact.c,v 1.12 91/02/19 10:05:13 mao Exp Locker: mao $ d166 1 a166 1 RcsId("$Header: RCS/xact.c,v 1.12 91/02/19 10:05:13 mao Exp Locker: mao $"); d1307 5 a1311 6 * here we were inside a transaction block and we * got an abort command from the user, so we move to * the abort state, do the abort processing and * then return. We remain in the abort state until * the user explicitly gives us an END TRANSACTION. * Hence, BEGIN and END will always match. d1337 3 a1339 4 /* ---------------------------------------------------------------- * traps to catch routines using these old routines -- * anything using these should be rewritten. * ---------------------------------------------------------------- a1340 1 d1342 1 a1342 1 UserErrorEndWithoutBegin() d1344 1 a1344 3 elog(DEBUG, "UserErrorEndWithoutBegin obsoleted"); abort(); } d1346 32 a1377 6 void UserErrorBeginAfterBegin() { elog(DEBUG, "UserErrorBeginAfterBegin obsoleted"); abort(); } d1379 11 a1389 103 void UserErrorAbortWithoutBegin() { elog(DEBUG, "UserErrorAbortWithoutBegin obsoleted"); abort(); } void InternalErrorIllegalStateTransition() { elog(DEBUG, "InternalErrorIllegalStateTransition obsoleted"); abort(); } void FsaMachine() { elog(DEBUG, "FsaMachine( obsoleted"); abort(); } void InitializeTransactionState() { elog(DEBUG, "InitializeTransactionState obsoleted"); abort(); } void OverrideTransactionState() { elog(DEBUG, "OverrideTransactionState obsoleted"); abort(); } bool IsBlockTransactionState() { elog(DEBUG, "IsBlockTransactionState obsoleted"); abort(); } bool IsOverrideTransactionState() { elog(DEBUG, "IsOverrideTransactionState obsoleted"); abort(); } void StartTransactionStateBlock() { elog(DEBUG, "StartTransactionStateBlock obsoleted"); abort(); } void StartTransactionStateCommand() { elog(DEBUG, "StartTransactionStateCommand obsoleted"); abort(); } void CommitTransactionStateCommand() { elog(DEBUG, "CommitTransactionStateCommand obsoleted"); abort(); } void CommitTransactionStateBlock() { elog(DEBUG, "CommitTransactionStateBlock obsoleted"); abort(); } void AbortCurrentTransactionState() { elog(DEBUG, "AbortCurrentTransactionState obsoleted"); abort(); } void AbortTransactionStateBlock() { elog(DEBUG, "AbortTransactionStateBlock obsoleted"); abort(); } void StartTransactionBlock() { elog(DEBUG, "StartTransactionBlock obsoleted"); abort(); } void CommitTransactionBlock() { elog(DEBUG, "CommitTransactionBlock obsoleted"); abort(); @ 1.12 log @don't elog(NOTICE, ...) when we're not in default transaction state and get a start command (this happens w/ every monitor command) @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.11 91/01/30 11:00:11 hong Exp Locker: mao $ d132 1 a132 1 RcsId("$Header: RCS/xact.c,v 1.11 91/01/30 11:00:11 hong Exp Locker: mao $"); d425 3 @ 1.11 log @fixed a synchronization problem @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.10 91/01/25 22:10:49 hong Exp $ d132 1 a132 1 RcsId("$Header: RCS/xact.c,v 1.10 91/01/25 22:10:49 hong Exp $"); d704 10 a713 2 if (s->state != TRANS_DEFAULT) elog(NOTICE, "StartTransaction and not in default state"); @ 1.10 log @cleaned up spinlock code @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.9 91/01/18 21:22:38 hong Exp Locker: hong $ a130 1 #include "storage/spin.h" d132 1 a132 2 extern SPINLOCK BufMgrLock; RcsId("$Header: RCS/xact.c,v 1.9 91/01/18 21:22:38 hong Exp Locker: hong $"); a575 6 /* ---------------- * XXX should be in lmgr * ---------------- */ SpinRelease(BufMgrLock); a661 6 /* ---------------- * XXX should be in lmgr * ---------------- */ SpinRelease(BufMgrLock); @ 1.9 log @for new buffer manager @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.8 90/09/21 11:58:11 cimarron Exp Locker: hong $ d133 2 a134 2 extern SPINLOCK *BufMgrLock; RcsId("$Header: RCS/xact.c,v 1.8 90/09/21 11:58:11 cimarron Exp Locker: hong $"); @ 1.8 log @added a fix to cure the problem of losing committed transaction discovered by jeff. @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.7 90/08/13 18:05:19 cimarron Exp Locker: cimarron $ d131 1 a131 1 RcsId("$Header: RCS/xact.c,v 1.7 90/08/13 18:05:19 cimarron Exp Locker: cimarron $"); d133 3 d583 1 a583 1 ImmediateReleaseBufSem(); d675 1 a675 1 ImmediateReleaseBufSem(); @ 1.7 log @added pathnames to include statements @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.6 90/08/08 16:10:36 plai Exp Locker: cimarron $ d131 1 a131 1 RcsId("$Header: RCS/xact.c,v 1.6 90/08/08 16:10:36 plai Exp Locker: cimarron $"); d528 6 @ 1.6 log @changed RecordTransactionCommit and RecordTransactionAbort to fix a bug that occurs when stable main memory is asumed (i.e. -S flag is on) @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.5 90/07/11 16:48:46 mao Version_2 $ d130 2 a131 2 #include "xact.h" RcsId("$Header: RCS/xact.c,v 1.5 90/07/11 16:48:46 mao Version_2 $"); @ 1.5 log @no longer need to init database id at first transaction -- this is done before we get into the first xact. @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.4 90/06/02 14:16:38 cimarron Exp Locker: mao $ d131 1 a131 1 RcsId("$Header: RCS/xact.c,v 1.4 90/06/02 14:16:38 cimarron Exp Locker: mao $"); d516 2 a517 1 * main memory this should be a no-op. d520 1 a520 2 if (TransactionFlushEnabled()) BufferManagerFlush(); d623 2 a624 1 * main memory this should be a no-op. d627 1 a627 2 if (TransactionFlushEnabled()) BufferManagerFlush(); @ 1.4 log @added IsAbortedTransactionBlockState() @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.3 90/05/16 13:56:02 cimarron Exp $ d131 1 a131 1 RcsId("$Header: RCS/xact.c,v 1.3 90/05/16 13:56:02 cimarron Exp $"); a730 11 /* ---------------- * XXX where should we do this? someplace around transaction * initialization but I don't understand its real purpose. * -cim 3/19/90 * ---------------- */ if (! TransactionInitWasProcessed) { InitMyDatabaseId(); TransactionInitWasProcessed = true; } @ 1.3 log @added code to disable flushing of dirty pages at the end of a transaction, under the assumption of stable main memory. @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.2 90/03/31 18:50:56 cimarron Exp $ d131 1 a131 1 RcsId("$Header: RCS/xact.c,v 1.2 90/03/31 18:50:56 cimarron Exp $"); d245 18 @ 1.2 log @added parallel transaction sync stuff @ text @d126 1 a126 1 * $Header: RCS/xact.c,v 1.1 90/03/26 20:32:39 cimarron Exp $ d131 1 a131 1 RcsId("$Header: RCS/xact.c,v 1.1 90/03/26 20:32:39 cimarron Exp $"); d199 27 d501 2 a502 1 BufferManagerFlush(); d608 2 a609 1 BufferManagerFlush(); @ 1.1 log @Initial revision @ text @d17 4 d113 12 d126 1 a126 1 * $Header$ d131 1 a131 1 RcsId("$Header$"); d134 6 a139 1 * global variable holding the current transaction state d150 3 d154 7 d208 1 a208 1 TransactionState s = &CurrentTransactionStateData; d235 1 a235 1 TransactionState s = &CurrentTransactionStateData; d261 1 a261 1 TransactionState s = &CurrentTransactionStateData; d286 1 a286 1 TransactionState s = &CurrentTransactionStateData; d307 1 a307 1 TransactionState s = &CurrentTransactionStateData; d329 1 a329 1 TransactionState s = &CurrentTransactionStateData; d347 1 a347 1 TransactionState s = &CurrentTransactionStateData; d633 1 a633 1 * portal memory context (unitl the next transaction). d652 1 a652 1 TransactionState s = &CurrentTransactionStateData; d720 1 a720 1 TransactionState s = &CurrentTransactionStateData; d764 1 a764 1 TransactionState s = &CurrentTransactionStateData; d801 79 d893 1 a893 1 TransactionState s = &CurrentTransactionStateData; d972 1 a972 1 TransactionState s = &CurrentTransactionStateData; d1046 1 a1046 1 TransactionState s = &CurrentTransactionStateData; d1128 1 a1128 1 TransactionState s = &CurrentTransactionStateData; d1166 1 a1166 1 TransactionState s = &CurrentTransactionStateData; d1220 1 a1220 1 TransactionState s = &CurrentTransactionStateData; @