]> granicus.if.org Git - postgresql/blob - src/backend/access/transam/xact.c
Ensure that catcache 'busy' flags are reset at transaction abort.
[postgresql] / src / backend / access / transam / xact.c
1 /*-------------------------------------------------------------------------
2  *
3  * xact.c
4  *        top level transaction system support routines
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.70 2000/08/06 04:17:47 tgl Exp $
12  *
13  * NOTES
14  *              Transaction aborts can now occur two ways:
15  *
16  *              1)      system dies from some internal cause  (Assert, etc..)
17  *              2)      user types abort
18  *
19  *              These two cases used to be treated identically, but now
20  *              we need to distinguish them.  Why?      consider the following
21  *              two situations:
22  *
23  *                              case 1                                                  case 2
24  *                              ------                                                  ------
25  *              1) user types BEGIN                             1) user types BEGIN
26  *              2) user does something                  2) user does something
27  *              3) user does not like what              3) system aborts for some reason
28  *                 she sees and types ABORT
29  *
30  *              In case 1, we want to abort the transaction and return to the
31  *              default state.  In case 2, there may be more commands coming
32  *              our way which are part of the same transaction block and we have
33  *              to ignore these commands until we see an END transaction.
34  *              (or an ABORT! --djm)
35  *
36  *              Internal aborts are now handled by AbortTransactionBlock(), just as
37  *              they always have been, and user aborts are now handled by
38  *              UserAbortTransactionBlock().  Both of them rely on AbortTransaction()
39  *              to do all the real work.  The only difference is what state we
40  *              enter after AbortTransaction() does its work:
41  *
42  *              * AbortTransactionBlock() leaves us in TBLOCK_ABORT and
43  *              * UserAbortTransactionBlock() leaves us in TBLOCK_ENDABORT
44  *
45  *              Low-level transaction abort handling is divided into two phases:
46  *              * AbortTransaction() executes as soon as we realize the transaction
47  *                has failed.  It should release all shared resources (locks etc)
48  *                so that we do not delay other backends unnecessarily.
49  *              * CleanupTransaction() executes when we finally see a user COMMIT
50  *                or ROLLBACK command; it cleans things up and gets us out of
51  *                the transaction internally.  In particular, we mustn't destroy
52  *                TransactionCommandContext until this point.
53  *
54  *       NOTES
55  *              This file is an attempt at a redesign of the upper layer
56  *              of the V1 transaction system which was too poorly thought
57  *              out to describe.  This new system hopes to be both simpler
58  *              in design, simpler to extend and needs to contain added
59  *              functionality to solve problems beyond the scope of the V1
60  *              system.  (In particuler, communication of transaction
61  *              information between parallel backends has to be supported)
62  *
63  *              The essential aspects of the transaction system are:
64  *
65  *                              o  transaction id generation
66  *                              o  transaction log updating
67  *                              o  memory cleanup
68  *                              o  cache invalidation
69  *                              o  lock cleanup
70  *
71  *              Hence, the functional division of the transaction code is
72  *              based on what of the above things need to be done during
73  *              a start/commit/abort transaction.  For instance, the
74  *              routine AtCommit_Memory() takes care of all the memory
75  *              cleanup stuff done at commit time.
76  *
77  *              The code is layered as follows:
78  *
79  *                              StartTransaction
80  *                              CommitTransaction
81  *                              AbortTransaction
82  *                              CleanupTransaction
83  *
84  *              are provided to do the lower level work like recording
85  *              the transaction status in the log and doing memory cleanup.
86  *              above these routines are another set of functions:
87  *
88  *                              StartTransactionCommand
89  *                              CommitTransactionCommand
90  *                              AbortCurrentTransaction
91  *
92  *              These are the routines used in the postgres main processing
93  *              loop.  They are sensitive to the current transaction block state
94  *              and make calls to the lower level routines appropriately.
95  *
96  *              Support for transaction blocks is provided via the functions:
97  *
98  *                              StartTransactionBlock
99  *                              CommitTransactionBlock
100  *                              AbortTransactionBlock
101  *
102  *              These are invoked only in responce to a user "BEGIN", "END",
103  *              or "ABORT" command.  The tricky part about these functions
104  *              is that they are called within the postgres main loop, in between
105  *              the StartTransactionCommand() and CommitTransactionCommand().
106  *
107  *              For example, consider the following sequence of user commands:
108  *
109  *              1)              begin
110  *              2)              retrieve (foo.all)
111  *              3)              append foo (bar = baz)
112  *              4)              end
113  *
114  *              in the main processing loop, this results in the following
115  *              transaction sequence:
116  *
117  *                      /       StartTransactionCommand();
118  *              1) /    ProcessUtility();                               << begin
119  *                 \            StartTransactionBlock();
120  *                      \       CommitTransactionCommand();
121  *
122  *                      /       StartTransactionCommand();
123  *              2) <    ProcessQuery();                                 << retrieve (foo.all)
124  *                      \       CommitTransactionCommand();
125  *
126  *                      /       StartTransactionCommand();
127  *              3) <    ProcessQuery();                                 << append foo (bar = baz)
128  *                      \       CommitTransactionCommand();
129  *
130  *                      /       StartTransactionCommand();
131  *              4) /    ProcessUtility();                               << end
132  *                 \            CommitTransactionBlock();
133  *                      \       CommitTransactionCommand();
134  *
135  *              The point of this example is to demonstrate the need for
136  *              StartTransactionCommand() and CommitTransactionCommand() to
137  *              be state smart -- they should do nothing in between the calls
138  *              to StartTransactionBlock() and EndTransactionBlock() and
139  *              outside these calls they need to do normal start/commit
140  *              processing.
141  *
142  *              Furthermore, suppose the "retrieve (foo.all)" caused an abort
143  *              condition.      We would then want to abort the transaction and
144  *              ignore all subsequent commands up to the "end".
145  *              -cim 3/23/90
146  *
147  *-------------------------------------------------------------------------
148  */
149
150 /*
151  * Large object clean up added in CommitTransaction() to prevent buffer leaks.
152  * [PA, 7/17/98]
153  * [PA] is Pascal AndrĂ© <andre@via.ecp.fr>
154  */
155 #include "postgres.h"
156
157 #include "access/nbtree.h"
158 #include "catalog/heap.h"
159 #include "catalog/index.h"
160 #include "commands/async.h"
161 #include "commands/sequence.h"
162 #include "commands/trigger.h"
163 #include "executor/spi.h"
164 #include "libpq/be-fsstubs.h"
165 #include "storage/proc.h"
166 #include "storage/sinval.h"
167 #include "utils/inval.h"
168 #include "utils/memutils.h"
169 #include "utils/portal.h"
170 #include "utils/catcache.h"
171 #include "utils/relcache.h"
172 #include "utils/temprel.h"
173
174 extern bool SharedBufferChanged;
175
176 static void AbortTransaction(void);
177 static void AtAbort_Cache(void);
178 static void AtAbort_Locks(void);
179 static void AtAbort_Memory(void);
180 static void AtCleanup_Memory(void);
181 static void AtCommit_Cache(void);
182 static void AtCommit_LocalCache(void);
183 static void AtCommit_Locks(void);
184 static void AtCommit_Memory(void);
185 static void AtStart_Cache(void);
186 static void AtStart_Locks(void);
187 static void AtStart_Memory(void);
188 static void CleanupTransaction(void);
189 static void CommitTransaction(void);
190 static void RecordTransactionAbort(void);
191 static void RecordTransactionCommit(void);
192 static void StartTransaction(void);
193
194 /* ----------------
195  *              global variables holding the current transaction state.
196  *
197  *              Note: when we are running several slave processes, the
198  *                        current transaction state data is copied into shared memory
199  *                        and the CurrentTransactionState pointer changed to
200  *                        point to the shared copy.  All this occurrs in slaves.c
201  * ----------------
202  */
203 TransactionStateData CurrentTransactionStateData = {
204         0,                                                      /* transaction id */
205         FirstCommandId,                         /* command id */
206         0,                                                      /* scan command id */
207         0x0,                                            /* start time */
208         TRANS_DEFAULT,                          /* transaction state */
209         TBLOCK_DEFAULT                          /* transaction block state */
210 };
211
212 TransactionState CurrentTransactionState = &CurrentTransactionStateData;
213
214 int                     DefaultXactIsoLevel = XACT_READ_COMMITTED;
215 int                     XactIsoLevel;
216
217 /* ----------------
218  *              info returned when the system is disabled
219  *
220  * Apparently a lot of this code is inherited from other prototype systems.
221  * For DisabledStartTime, use a symbolic value to make the relationships clearer.
222  * The old value of 1073741823 corresponds to a date in y2004, which is coming closer
223  *      every day. It appears that if we return a value guaranteed larger than
224  *      any real time associated with a transaction then comparisons in other
225  *      modules will still be correct. Let's use BIG_ABSTIME for this. tgl 2/14/97
226  *
227  *              Note:  I have no idea what the significance of the
228  *                         1073741823 in DisabledStartTime.. I just carried
229  *                         this over when converting things from the old
230  *                         V1 transaction system.  -cim 3/18/90
231  * ----------------
232  */
233 TransactionId DisabledTransactionId = (TransactionId) -1;
234
235 CommandId       DisabledCommandId = (CommandId) -1;
236
237 AbsoluteTime DisabledStartTime = (AbsoluteTime) BIG_ABSTIME;    /* 1073741823; */
238
239 /* ----------------
240  *              overflow flag
241  * ----------------
242  */
243 bool            CommandIdCounterOverflowFlag;
244
245 /* ----------------
246  *              catalog creation transaction bootstrapping flag.
247  *              This should be eliminated and added to the transaction
248  *              state stuff.  -cim 3/19/90
249  * ----------------
250  */
251 bool            AMI_OVERRIDE = false;
252
253 /* ----------------------------------------------------------------
254  *                                       transaction state accessors
255  * ----------------------------------------------------------------
256  */
257
258 /* --------------------------------
259  *              TranactionFlushEnabled()
260  *              SetTransactionFlushEnabled()
261  *
262  *              These are used to test and set the "TransactionFlushState"
263  *              varable.  If this variable is true (the default), then
264  *              the system will flush all dirty buffers to disk at the end
265  *              of each transaction.   If false then we are assuming the
266  *              buffer pool resides in stable main memory, in which case we
267  *              only do writes as necessary.
268  * --------------------------------
269  */
270 static int      TransactionFlushState = 1;
271
272 int
273 TransactionFlushEnabled(void)
274 {
275         return TransactionFlushState;
276 }
277
278 #ifdef NOT_USED
279 void
280 SetTransactionFlushEnabled(bool state)
281 {
282         TransactionFlushState = (state == true);
283 }
284
285
286 /* --------------------------------
287  *              IsTransactionState
288  *
289  *              This returns true if we are currently running a query
290  *              within an executing transaction.
291  * --------------------------------
292  */
293 bool
294 IsTransactionState(void)
295 {
296         TransactionState s = CurrentTransactionState;
297
298         switch (s->state)
299         {
300                 case TRANS_DEFAULT:
301                         return false;
302                 case TRANS_START:
303                         return true;
304                 case TRANS_INPROGRESS:
305                         return true;
306                 case TRANS_COMMIT:
307                         return true;
308                 case TRANS_ABORT:
309                         return true;
310                 case TRANS_DISABLED:
311                         return false;
312         }
313
314         /*
315          * Shouldn't get here, but lint is not happy with this...
316          */
317         return false;
318 }
319
320 #endif
321
322 /* --------------------------------
323  *              IsAbortedTransactionBlockState
324  *
325  *              This returns true if we are currently running a query
326  *              within an aborted transaction block.
327  * --------------------------------
328  */
329 bool
330 IsAbortedTransactionBlockState()
331 {
332         TransactionState s = CurrentTransactionState;
333
334         if (s->blockState == TBLOCK_ABORT)
335                 return true;
336
337         return false;
338 }
339
340 /* --------------------------------
341  *              OverrideTransactionSystem
342  *
343  *              This is used to temporarily disable the transaction
344  *              processing system in order to do initialization of
345  *              the transaction system data structures and relations
346  *              themselves.
347  * --------------------------------
348  */
349 int                     SavedTransactionState;
350
351 void
352 OverrideTransactionSystem(bool flag)
353 {
354         TransactionState s = CurrentTransactionState;
355
356         if (flag == true)
357         {
358                 if (s->state == TRANS_DISABLED)
359                         return;
360
361                 SavedTransactionState = s->state;
362                 s->state = TRANS_DISABLED;
363         }
364         else
365         {
366                 if (s->state != TRANS_DISABLED)
367                         return;
368
369                 s->state = SavedTransactionState;
370         }
371 }
372
373 /* --------------------------------
374  *              GetCurrentTransactionId
375  *
376  *              This returns the id of the current transaction, or
377  *              the id of the "disabled" transaction.
378  * --------------------------------
379  */
380 TransactionId
381 GetCurrentTransactionId()
382 {
383         TransactionState s = CurrentTransactionState;
384
385         /* ----------------
386          *      if the transaction system is disabled, we return
387          *      the special "disabled" transaction id.
388          * ----------------
389          */
390         if (s->state == TRANS_DISABLED)
391                 return (TransactionId) DisabledTransactionId;
392
393         /* ----------------
394          *      otherwise return the current transaction id.
395          * ----------------
396          */
397         return (TransactionId) s->transactionIdData;
398 }
399
400
401 /* --------------------------------
402  *              GetCurrentCommandId
403  * --------------------------------
404  */
405 CommandId
406 GetCurrentCommandId()
407 {
408         TransactionState s = CurrentTransactionState;
409
410         /* ----------------
411          *      if the transaction system is disabled, we return
412          *      the special "disabled" command id.
413          * ----------------
414          */
415         if (s->state == TRANS_DISABLED)
416                 return (CommandId) DisabledCommandId;
417
418         return s->commandId;
419 }
420
421 CommandId
422 GetScanCommandId()
423 {
424         TransactionState s = CurrentTransactionState;
425
426         /* ----------------
427          *      if the transaction system is disabled, we return
428          *      the special "disabled" command id.
429          * ----------------
430          */
431         if (s->state == TRANS_DISABLED)
432                 return (CommandId) DisabledCommandId;
433
434         return s->scanCommandId;
435 }
436
437
438 /* --------------------------------
439  *              GetCurrentTransactionStartTime
440  * --------------------------------
441  */
442 AbsoluteTime
443 GetCurrentTransactionStartTime()
444 {
445         TransactionState s = CurrentTransactionState;
446
447         /* ----------------
448          *      if the transaction system is disabled, we return
449          *      the special "disabled" starting time.
450          * ----------------
451          */
452         if (s->state == TRANS_DISABLED)
453                 return (AbsoluteTime) DisabledStartTime;
454
455         return s->startTime;
456 }
457
458
459 /* --------------------------------
460  *              TransactionIdIsCurrentTransactionId
461  * --------------------------------
462  */
463 bool
464 TransactionIdIsCurrentTransactionId(TransactionId xid)
465 {
466         TransactionState s = CurrentTransactionState;
467
468         if (AMI_OVERRIDE)
469                 return false;
470
471         return (bool)
472                 TransactionIdEquals(xid, s->transactionIdData);
473 }
474
475
476 /* --------------------------------
477  *              CommandIdIsCurrentCommandId
478  * --------------------------------
479  */
480 bool
481 CommandIdIsCurrentCommandId(CommandId cid)
482 {
483         TransactionState s = CurrentTransactionState;
484
485         if (AMI_OVERRIDE)
486                 return false;
487
488         return (cid == s->commandId) ? true : false;
489 }
490
491 bool
492 CommandIdGEScanCommandId(CommandId cid)
493 {
494         TransactionState s = CurrentTransactionState;
495
496         if (AMI_OVERRIDE)
497                 return false;
498
499         return (cid >= s->scanCommandId) ? true : false;
500 }
501
502
503 /* --------------------------------
504  *              ClearCommandIdCounterOverflowFlag
505  * --------------------------------
506  */
507 #ifdef NOT_USED
508 void
509 ClearCommandIdCounterOverflowFlag()
510 {
511         CommandIdCounterOverflowFlag = false;
512 }
513
514 #endif
515
516 /* --------------------------------
517  *              CommandCounterIncrement
518  * --------------------------------
519  */
520 void
521 CommandCounterIncrement()
522 {
523         CurrentTransactionStateData.commandId += 1;
524         if (CurrentTransactionStateData.commandId == FirstCommandId)
525         {
526                 CommandIdCounterOverflowFlag = true;
527                 elog(ERROR, "You may only have 2^32-1 commands per transaction");
528         }
529
530         CurrentTransactionStateData.scanCommandId = CurrentTransactionStateData.commandId;
531
532         /*
533          * make cache changes visible to me.  AtCommit_LocalCache() instead of
534          * AtCommit_Cache() is called here.
535          */
536         AtCommit_LocalCache();
537         AtStart_Cache();
538
539 }
540
541 void
542 SetScanCommandId(CommandId savedId)
543 {
544
545         CurrentTransactionStateData.scanCommandId = savedId;
546
547 }
548
549 /* ----------------------------------------------------------------
550  *                                              initialization stuff
551  * ----------------------------------------------------------------
552  */
553 void
554 InitializeTransactionSystem()
555 {
556         InitializeTransactionLog();
557 }
558
559 /* ----------------------------------------------------------------
560  *                                              StartTransaction stuff
561  * ----------------------------------------------------------------
562  */
563
564 /* --------------------------------
565  *              AtStart_Cache
566  * --------------------------------
567  */
568 static void
569 AtStart_Cache()
570 {
571         DiscardInvalid();
572 }
573
574 /* --------------------------------
575  *              AtStart_Locks
576  * --------------------------------
577  */
578 static void
579 AtStart_Locks()
580 {
581
582         /*
583          * at present, it is unknown to me what belongs here -cim 3/18/90
584          *
585          * There isn't anything to do at the start of a xact for locks. -mer
586          * 5/24/92
587          */
588 }
589
590 /* --------------------------------
591  *              AtStart_Memory
592  * --------------------------------
593  */
594 static void
595 AtStart_Memory()
596 {
597         /* ----------------
598          *      We shouldn't have any transaction contexts already.
599          * ----------------
600          */
601         Assert(TopTransactionContext == NULL);
602         Assert(TransactionCommandContext == NULL);
603
604         /* ----------------
605          *      Create a toplevel context for the transaction.
606          * ----------------
607          */
608         TopTransactionContext =
609                 AllocSetContextCreate(TopMemoryContext,
610                                                           "TopTransactionContext",
611                                                           ALLOCSET_DEFAULT_MINSIZE,
612                                                           ALLOCSET_DEFAULT_INITSIZE,
613                                                           ALLOCSET_DEFAULT_MAXSIZE);
614
615         /* ----------------
616          *      Create a statement-level context and make it active.
617          * ----------------
618          */
619         TransactionCommandContext =
620                 AllocSetContextCreate(TopTransactionContext,
621                                                           "TransactionCommandContext",
622                                                           ALLOCSET_DEFAULT_MINSIZE,
623                                                           ALLOCSET_DEFAULT_INITSIZE,
624                                                           ALLOCSET_DEFAULT_MAXSIZE);
625         MemoryContextSwitchTo(TransactionCommandContext);
626 }
627
628
629 /* ----------------------------------------------------------------
630  *                                              CommitTransaction stuff
631  * ----------------------------------------------------------------
632  */
633
634 /* --------------------------------
635  *              RecordTransactionCommit
636  *
637  *              Note: the two calls to BufferManagerFlush() exist to ensure
638  *                        that data pages are written before log pages.  These
639  *                        explicit calls should be replaced by a more efficient
640  *                        ordered page write scheme in the buffer manager
641  *                        -cim 3/18/90
642  * --------------------------------
643  */
644 static void
645 RecordTransactionCommit()
646 {
647         TransactionId xid;
648         int                     leak;
649
650         /* ----------------
651          *      get the current transaction id
652          * ----------------
653          */
654         xid = GetCurrentTransactionId();
655
656         /*
657          * flush the buffer manager pages.      Note: if we have stable main
658          * memory, dirty shared buffers are not flushed plai 8/7/90
659          */
660         leak = BufferPoolCheckLeak();
661
662         /*
663          * If no one shared buffer was changed by this transaction then we
664          * don't flush shared buffers and don't record commit status.
665          */
666         if (SharedBufferChanged)
667         {
668                 FlushBufferPool();
669                 if (leak)
670                         ResetBufferPool(true);
671
672                 /*
673                  * have the transaction access methods record the status of this
674                  * transaction id in the pg_log relation.
675                  */
676                 TransactionIdCommit(xid);
677
678                 /*
679                  * Now write the log info to the disk too.
680                  */
681                 leak = BufferPoolCheckLeak();
682                 FlushBufferPool();
683         }
684
685         if (leak)
686                 ResetBufferPool(true);
687 }
688
689
690 /* --------------------------------
691  *              AtCommit_Cache
692  * --------------------------------
693  */
694 static void
695 AtCommit_Cache()
696 {
697         /* ----------------
698          * Make catalog changes visible to all backend.
699          * ----------------
700          */
701         RegisterInvalid(true);
702 }
703
704 /* --------------------------------
705  *              AtCommit_LocalCache
706  * --------------------------------
707  */
708 static void
709 AtCommit_LocalCache()
710 {
711         /* ----------------
712          * Make catalog changes visible to me for the next command.
713          * ----------------
714          */
715         ImmediateLocalInvalidation(true);
716 }
717
718 /* --------------------------------
719  *              AtCommit_Locks
720  * --------------------------------
721  */
722 static void
723 AtCommit_Locks()
724 {
725         /* ----------------
726          *      XXX What if ProcReleaseLocks fails?  (race condition?)
727          *
728          *      Then you're up a creek! -mer 5/24/92
729          * ----------------
730          */
731         ProcReleaseLocks();
732 }
733
734 /* --------------------------------
735  *              AtCommit_Memory
736  * --------------------------------
737  */
738 static void
739 AtCommit_Memory()
740 {
741         /* ----------------
742          *      Now that we're "out" of a transaction, have the
743          *      system allocate things in the top memory context instead
744          *      of per-transaction contexts.
745          * ----------------
746          */
747         MemoryContextSwitchTo(TopMemoryContext);
748
749         /* ----------------
750          *      Release all transaction-local memory.
751          * ----------------
752          */
753         Assert(TopTransactionContext != NULL);
754         MemoryContextDelete(TopTransactionContext);
755         TopTransactionContext = NULL;
756         TransactionCommandContext = NULL;
757 }
758
759 /* ----------------------------------------------------------------
760  *                                              AbortTransaction stuff
761  * ----------------------------------------------------------------
762  */
763
764 /* --------------------------------
765  *              RecordTransactionAbort
766  * --------------------------------
767  */
768 static void
769 RecordTransactionAbort()
770 {
771         TransactionId xid;
772
773         /* ----------------
774          *      get the current transaction id
775          * ----------------
776          */
777         xid = GetCurrentTransactionId();
778
779         /*
780          * Have the transaction access methods record the status of this
781          * transaction id in the pg_log relation. We skip it if no one shared
782          * buffer was changed by this transaction.
783          */
784         if (SharedBufferChanged && !TransactionIdDidCommit(xid))
785                 TransactionIdAbort(xid);
786
787         /*
788          * Tell bufmgr and smgr to release resources.
789          */
790         ResetBufferPool(false);         /* false -> is abort */
791 }
792
793 /* --------------------------------
794  *              AtAbort_Cache
795  * --------------------------------
796  */
797 static void
798 AtAbort_Cache()
799 {
800         RelationCacheAbort();
801         SystemCacheAbort();
802         RegisterInvalid(false);
803 }
804
805 /* --------------------------------
806  *              AtAbort_Locks
807  * --------------------------------
808  */
809 static void
810 AtAbort_Locks()
811 {
812         /* ----------------
813          *      XXX What if ProcReleaseLocks() fails?  (race condition?)
814          *
815          *      Then you're up a creek without a paddle! -mer
816          * ----------------
817          */
818         ProcReleaseLocks();
819 }
820
821
822 /* --------------------------------
823  *              AtAbort_Memory
824  * --------------------------------
825  */
826 static void
827 AtAbort_Memory()
828 {
829         /* ----------------
830          *      Make sure we are in a valid context (not a child of
831          *      TransactionCommandContext...).  Note that it is possible
832          *      for this code to be called when we aren't in a transaction
833          *      at all; go directly to TopMemoryContext in that case.
834          * ----------------
835          */
836         if (TransactionCommandContext != NULL)
837         {
838                 MemoryContextSwitchTo(TransactionCommandContext);
839
840                 /* ----------------
841                  *      We do not want to destroy transaction contexts yet,
842                  *      but it should be OK to delete any command-local memory.
843                  * ----------------
844                  */
845                 MemoryContextResetAndDeleteChildren(TransactionCommandContext);
846         }
847         else
848         {
849                 MemoryContextSwitchTo(TopMemoryContext);
850         }
851 }
852
853
854 /* ----------------------------------------------------------------
855  *                                              CleanupTransaction stuff
856  * ----------------------------------------------------------------
857  */
858
859 /* --------------------------------
860  *              AtCleanup_Memory
861  * --------------------------------
862  */
863 static void
864 AtCleanup_Memory()
865 {
866         /* ----------------
867          *      Now that we're "out" of a transaction, have the
868          *      system allocate things in the top memory context instead
869          *      of per-transaction contexts.
870          * ----------------
871          */
872         MemoryContextSwitchTo(TopMemoryContext);
873
874         /* ----------------
875          *      Release all transaction-local memory.
876          * ----------------
877          */
878         if (TopTransactionContext != NULL)
879                 MemoryContextDelete(TopTransactionContext);
880         TopTransactionContext = NULL;
881         TransactionCommandContext = NULL;
882 }
883
884
885 /* ----------------------------------------------------------------
886  *                                              interface routines
887  * ----------------------------------------------------------------
888  */
889
890 /* --------------------------------
891  *              StartTransaction
892  *
893  * --------------------------------
894  */
895 static void
896 StartTransaction()
897 {
898         TransactionState s = CurrentTransactionState;
899
900         FreeXactSnapshot();
901         XactIsoLevel = DefaultXactIsoLevel;
902
903         /* ----------------
904          *      Check the current transaction state.  If the transaction system
905          *      is switched off, or if we're already in a transaction, do nothing.
906          *      We're already in a transaction when the monitor sends a null
907          *      command to the backend to flush the comm channel.  This is a
908          *      hacky fix to a communications problem, and we keep having to
909          *      deal with it here.      We should fix the comm channel code.  mao 080891
910          * ----------------
911          */
912         if (s->state == TRANS_DISABLED || s->state == TRANS_INPROGRESS)
913                 return;
914
915         /* ----------------
916          *      set the current transaction state information
917          *      appropriately during start processing
918          * ----------------
919          */
920         s->state = TRANS_START;
921
922         SetReindexProcessing(false);
923
924         /* ----------------
925          *      generate a new transaction id
926          * ----------------
927          */
928         GetNewTransactionId(&(s->transactionIdData));
929
930         XactLockTableInsert(s->transactionIdData);
931
932         /* ----------------
933          *      initialize current transaction state fields
934          * ----------------
935          */
936         s->commandId = FirstCommandId;
937         s->scanCommandId = FirstCommandId;
938         s->startTime = GetCurrentAbsoluteTime();
939
940         /* ----------------
941          *      initialize the various transaction subsystems
942          * ----------------
943          */
944         AtStart_Memory();
945         AtStart_Cache();
946         AtStart_Locks();
947
948         /* ----------------
949          *      Tell the trigger manager to we're starting a transaction
950          * ----------------
951          */
952         DeferredTriggerBeginXact();
953
954         /* ----------------
955          *      done with start processing, set current transaction
956          *      state to "in progress"
957          * ----------------
958          */
959         s->state = TRANS_INPROGRESS;
960
961 }
962
963 #ifdef NOT_USED
964 /* ---------------
965  * Tell me if we are currently in progress
966  * ---------------
967  */
968 bool
969 CurrentXactInProgress()
970 {
971         return CurrentTransactionState->state == TRANS_INPROGRESS;
972 }
973 #endif
974
975 /* --------------------------------
976  *              CommitTransaction
977  *
978  * --------------------------------
979  */
980 static void
981 CommitTransaction()
982 {
983         TransactionState s = CurrentTransactionState;
984
985         /* ----------------
986          *      check the current transaction state
987          * ----------------
988          */
989         if (s->state == TRANS_DISABLED)
990                 return;
991
992         if (s->state != TRANS_INPROGRESS)
993                 elog(NOTICE, "CommitTransaction and not in in-progress state ");
994
995         /* ----------------
996          *      Tell the trigger manager that this transaction is about to be
997          *      committed. He'll invoke all trigger deferred until XACT before
998          *      we really start on committing the transaction.
999          * ----------------
1000          */
1001         DeferredTriggerEndXact();
1002
1003         /* ----------------
1004          *      set the current transaction state information
1005          *      appropriately during the abort processing
1006          * ----------------
1007          */
1008         s->state = TRANS_COMMIT;
1009
1010         /* ----------------
1011          *      do commit processing
1012          * ----------------
1013          */
1014
1015         /* handle commit for large objects [ PA, 7/17/98 ] */
1016         lo_commit(true);
1017
1018         /* NOTIFY commit must also come before lower-level cleanup */
1019         AtCommit_Notify();
1020
1021         CloseSequences();
1022         AtEOXact_portals();
1023         RecordTransactionCommit();
1024
1025         /*
1026          * Let others know about no transaction in progress by me. Note that
1027          * this must be done _before_ releasing locks we hold and
1028          * SpinAcquire(SInvalLock) is required: UPDATE with xid 0 is blocked
1029          * by xid 1' UPDATE, xid 1 is doing commit while xid 2 gets snapshot -
1030          * if xid 2' GetSnapshotData sees xid 1 as running then it must see
1031          * xid 0 as running as well or it will see two tuple versions - one
1032          * deleted by xid 1 and one inserted by xid 0.
1033          */
1034         if (MyProc != (PROC *) NULL)
1035         {
1036                 /* Lock SInvalLock because that's what GetSnapshotData uses. */
1037                 SpinAcquire(SInvalLock);
1038                 MyProc->xid = InvalidTransactionId;
1039                 MyProc->xmin = InvalidTransactionId;
1040                 SpinRelease(SInvalLock);
1041         }
1042
1043         RelationPurgeLocalRelation(true);
1044         AtEOXact_SPI();
1045         AtEOXact_nbtree();
1046         AtCommit_Cache();
1047         AtCommit_Locks();
1048         AtCommit_Memory();
1049         AtEOXact_Files();
1050
1051         SharedBufferChanged = false; /* safest place to do it */
1052
1053         /* ----------------
1054          *      done with commit processing, set current transaction
1055          *      state back to default
1056          * ----------------
1057          */
1058         s->state = TRANS_DEFAULT;
1059 }
1060
1061 /* --------------------------------
1062  *              AbortTransaction
1063  *
1064  * --------------------------------
1065  */
1066 static void
1067 AbortTransaction()
1068 {
1069         TransactionState s = CurrentTransactionState;
1070
1071         /*
1072          * Let others to know about no transaction in progress - vadim
1073          * 11/26/96
1074          */
1075         if (MyProc != (PROC *) NULL)
1076         {
1077                 MyProc->xid = InvalidTransactionId;
1078                 MyProc->xmin = InvalidTransactionId;
1079         }
1080
1081         /* ----------------
1082          *      check the current transaction state
1083          * ----------------
1084          */
1085         if (s->state == TRANS_DISABLED)
1086                 return;
1087
1088         if (s->state != TRANS_INPROGRESS)
1089                 elog(NOTICE, "AbortTransaction and not in in-progress state");
1090
1091         /* ----------------
1092          *      Tell the trigger manager that this transaction is about to be
1093          *      aborted.
1094          * ----------------
1095          */
1096         DeferredTriggerAbortXact();
1097
1098         /* ----------------
1099          *      set the current transaction state information
1100          *      appropriately during the abort processing
1101          * ----------------
1102          */
1103         s->state = TRANS_ABORT;
1104
1105         /* ----------------
1106          *      do abort processing
1107          * ----------------
1108          */
1109         lo_commit(false);                       /* 'false' means it's abort */
1110         UnlockBuffers();
1111         AtAbort_Notify();
1112         CloseSequences();
1113         AtEOXact_portals();
1114         RecordTransactionAbort();
1115         RelationPurgeLocalRelation(false);
1116         invalidate_temp_relations();
1117         AtEOXact_SPI();
1118         AtEOXact_nbtree();
1119         AtAbort_Cache();
1120         AtAbort_Locks();
1121         AtAbort_Memory();
1122         AtEOXact_Files();
1123
1124         SharedBufferChanged = false; /* safest place to do it */
1125
1126         /* ----------------
1127          *      State remains TRANS_ABORT until CleanupTransaction().
1128          * ----------------
1129          */
1130 }
1131
1132 /* --------------------------------
1133  *              CleanupTransaction
1134  *
1135  * --------------------------------
1136  */
1137 static void
1138 CleanupTransaction()
1139 {
1140         TransactionState s = CurrentTransactionState;
1141
1142         if (s->state == TRANS_DISABLED)
1143                 return;
1144
1145         /* ----------------
1146          *      State should still be TRANS_ABORT from AbortTransaction().
1147          * ----------------
1148          */
1149         if (s->state != TRANS_ABORT)
1150                 elog(FATAL, "CleanupTransaction and not in abort state");
1151
1152         /* ----------------
1153          *      do abort cleanup processing
1154          * ----------------
1155          */
1156         AtCleanup_Memory();
1157
1158         /* ----------------
1159          *      done with abort processing, set current transaction
1160          *      state back to default
1161          * ----------------
1162          */
1163         s->state = TRANS_DEFAULT;
1164 }
1165
1166 /* --------------------------------
1167  *              StartTransactionCommand
1168  * --------------------------------
1169  */
1170 void
1171 StartTransactionCommand()
1172 {
1173         TransactionState s = CurrentTransactionState;
1174
1175         switch (s->blockState)
1176         {
1177                         /* ----------------
1178                          *              if we aren't in a transaction block, we
1179                          *              just do our usual start transaction.
1180                          * ----------------
1181                          */
1182                 case TBLOCK_DEFAULT:
1183                         StartTransaction();
1184                         break;
1185
1186                         /* ----------------
1187                          *              We should never experience this -- if we do it
1188                          *              means the BEGIN state was not changed in the previous
1189                          *              CommitTransactionCommand().  If we get it, we print
1190                          *              a warning and change to the in-progress state.
1191                          * ----------------
1192                          */
1193                 case TBLOCK_BEGIN:
1194                         elog(NOTICE, "StartTransactionCommand: unexpected TBLOCK_BEGIN");
1195                         s->blockState = TBLOCK_INPROGRESS;
1196                         break;
1197
1198                         /* ----------------
1199                          *              This is the case when are somewhere in a transaction
1200                          *              block and about to start a new command.  For now we
1201                          *              do nothing but someday we may do command-local resource
1202                          *              initialization.
1203                          * ----------------
1204                          */
1205                 case TBLOCK_INPROGRESS:
1206                         break;
1207
1208                         /* ----------------
1209                          *              As with BEGIN, we should never experience this
1210                          *              if we do it means the END state was not changed in the
1211                          *              previous CommitTransactionCommand().  If we get it, we
1212                          *              print a warning, commit the transaction, start a new
1213                          *              transaction and change to the default state.
1214                          * ----------------
1215                          */
1216                 case TBLOCK_END:
1217                         elog(NOTICE, "StartTransactionCommand: unexpected TBLOCK_END");
1218                         s->blockState = TBLOCK_DEFAULT;
1219                         CommitTransaction();
1220                         StartTransaction();
1221                         break;
1222
1223                         /* ----------------
1224                          *              Here we are in the middle of a transaction block but
1225                          *              one of the commands caused an abort so we do nothing
1226                          *              but remain in the abort state.  Eventually we will get
1227                          *              to the "END TRANSACTION" which will set things straight.
1228                          * ----------------
1229                          */
1230                 case TBLOCK_ABORT:
1231                         break;
1232
1233                         /* ----------------
1234                          *              This means we somehow aborted and the last call to
1235                          *              CommitTransactionCommand() didn't clear the state so
1236                          *              we remain in the ENDABORT state and maybe next time
1237                          *              we get to CommitTransactionCommand() the state will
1238                          *              get reset to default.
1239                          * ----------------
1240                          */
1241                 case TBLOCK_ENDABORT:
1242                         elog(NOTICE, "StartTransactionCommand: unexpected TBLOCK_ENDABORT");
1243                         break;
1244         }
1245
1246         /*
1247          * We must switch to TransactionCommandContext before returning.
1248          * This is already done if we called StartTransaction, otherwise not.
1249          */
1250         Assert(TransactionCommandContext != NULL);
1251         MemoryContextSwitchTo(TransactionCommandContext);
1252 }
1253
1254 /* --------------------------------
1255  *              CommitTransactionCommand
1256  * --------------------------------
1257  */
1258 void
1259 CommitTransactionCommand()
1260 {
1261         TransactionState s = CurrentTransactionState;
1262
1263         switch (s->blockState)
1264         {
1265                         /* ----------------
1266                          *              if we aren't in a transaction block, we
1267                          *              just do our usual transaction commit
1268                          * ----------------
1269                          */
1270                 case TBLOCK_DEFAULT:
1271                         CommitTransaction();
1272                         break;
1273
1274                         /* ----------------
1275                          *              This is the case right after we get a "BEGIN TRANSACTION"
1276                          *              command, but the user hasn't done anything else yet, so
1277                          *              we change to the "transaction block in progress" state
1278                          *              and return.
1279                          * ----------------
1280                          */
1281                 case TBLOCK_BEGIN:
1282                         s->blockState = TBLOCK_INPROGRESS;
1283                         break;
1284
1285                         /* ----------------
1286                          *              This is the case when we have finished executing a command
1287                          *              someplace within a transaction block.  We increment the
1288                          *              command counter and return.  Someday we may free resources
1289                          *              local to the command.
1290                          *
1291                          *              That someday is today, at least for memory allocated in
1292                          *              TransactionCommandContext.
1293                          *                              - vadim 03/25/97
1294                          * ----------------
1295                          */
1296                 case TBLOCK_INPROGRESS:
1297                         CommandCounterIncrement();
1298                         MemoryContextResetAndDeleteChildren(TransactionCommandContext);
1299                         break;
1300
1301                         /* ----------------
1302                          *              This is the case when we just got the "END TRANSACTION"
1303                          *              statement, so we commit the transaction and go back to
1304                          *              the default state.
1305                          * ----------------
1306                          */
1307                 case TBLOCK_END:
1308                         CommitTransaction();
1309                         s->blockState = TBLOCK_DEFAULT;
1310                         break;
1311
1312                         /* ----------------
1313                          *              Here we are in the middle of a transaction block but
1314                          *              one of the commands caused an abort so we do nothing
1315                          *              but remain in the abort state.  Eventually we will get
1316                          *              to the "END TRANSACTION" which will set things straight.
1317                          * ----------------
1318                          */
1319                 case TBLOCK_ABORT:
1320                         break;
1321
1322                         /* ----------------
1323                          *              Here we were in an aborted transaction block which
1324                          *              just processed the "END TRANSACTION" command from the
1325                          *              user, so clean up and return to the default state.
1326                          * ----------------
1327                          */
1328                 case TBLOCK_ENDABORT:
1329                         CleanupTransaction();
1330                         s->blockState = TBLOCK_DEFAULT;
1331                         break;
1332         }
1333 }
1334
1335 /* --------------------------------
1336  *              AbortCurrentTransaction
1337  * --------------------------------
1338  */
1339 void
1340 AbortCurrentTransaction()
1341 {
1342         TransactionState s = CurrentTransactionState;
1343
1344         switch (s->blockState)
1345         {
1346                         /* ----------------
1347                          *              if we aren't in a transaction block, we
1348                          *              just do the basic abort & cleanup transaction.
1349                          * ----------------
1350                          */
1351                 case TBLOCK_DEFAULT:
1352                         AbortTransaction();
1353                         CleanupTransaction();
1354                         break;
1355
1356                         /* ----------------
1357                          *              If we are in the TBLOCK_BEGIN it means something
1358                          *              screwed up right after reading "BEGIN TRANSACTION"
1359                          *              so we enter the abort state.  Eventually an "END
1360                          *              TRANSACTION" will fix things.
1361                          * ----------------
1362                          */
1363                 case TBLOCK_BEGIN:
1364                         s->blockState = TBLOCK_ABORT;
1365                         AbortTransaction();
1366                         /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1367                         break;
1368
1369                         /* ----------------
1370                          *              This is the case when are somewhere in a transaction
1371                          *              block which aborted so we abort the transaction and
1372                          *              set the ABORT state.  Eventually an "END TRANSACTION"
1373                          *              will fix things and restore us to a normal state.
1374                          * ----------------
1375                          */
1376                 case TBLOCK_INPROGRESS:
1377                         s->blockState = TBLOCK_ABORT;
1378                         AbortTransaction();
1379                         /* CleanupTransaction happens when we exit TBLOCK_ABORT */
1380                         break;
1381
1382                         /* ----------------
1383                          *              Here, the system was fouled up just after the
1384                          *              user wanted to end the transaction block so we
1385                          *              abort the transaction and put us back into the
1386                          *              default state.
1387                          * ----------------
1388                          */
1389                 case TBLOCK_END:
1390                         s->blockState = TBLOCK_DEFAULT;
1391                         AbortTransaction();
1392                         CleanupTransaction();
1393                         break;
1394
1395                         /* ----------------
1396                          *              Here, we are already in an aborted transaction
1397                          *              state and are waiting for an "END TRANSACTION" to
1398                          *              come along and lo and behold, we abort again!
1399                          *              So we just remain in the abort state.
1400                          * ----------------
1401                          */
1402                 case TBLOCK_ABORT:
1403                         break;
1404
1405                         /* ----------------
1406                          *              Here we were in an aborted transaction block which
1407                          *              just processed the "END TRANSACTION" command but somehow
1408                          *              aborted again.. since we must have done the abort
1409                          *              processing, we clean up and return to the default state.
1410                          * ----------------
1411                          */
1412                 case TBLOCK_ENDABORT:
1413                         CleanupTransaction();
1414                         s->blockState = TBLOCK_DEFAULT;
1415                         break;
1416         }
1417 }
1418
1419 /* ----------------------------------------------------------------
1420  *                                         transaction block support
1421  * ----------------------------------------------------------------
1422  */
1423 /* --------------------------------
1424  *              BeginTransactionBlock
1425  * --------------------------------
1426  */
1427 void
1428 BeginTransactionBlock(void)
1429 {
1430         TransactionState s = CurrentTransactionState;
1431
1432         /* ----------------
1433          *      check the current transaction state
1434          * ----------------
1435          */
1436         if (s->state == TRANS_DISABLED)
1437                 return;
1438
1439         if (s->blockState != TBLOCK_DEFAULT)
1440                 elog(NOTICE, "BEGIN: already a transaction in progress");
1441
1442         /* ----------------
1443          *      set the current transaction block state information
1444          *      appropriately during begin processing
1445          * ----------------
1446          */
1447         s->blockState = TBLOCK_BEGIN;
1448
1449         /* ----------------
1450          *      do begin processing
1451          * ----------------
1452          */
1453
1454         /* ----------------
1455          *      done with begin processing, set block state to inprogress
1456          * ----------------
1457          */
1458         s->blockState = TBLOCK_INPROGRESS;
1459 }
1460
1461 /* --------------------------------
1462  *              EndTransactionBlock
1463  * --------------------------------
1464  */
1465 void
1466 EndTransactionBlock(void)
1467 {
1468         TransactionState s = CurrentTransactionState;
1469
1470         /* ----------------
1471          *      check the current transaction state
1472          * ----------------
1473          */
1474         if (s->state == TRANS_DISABLED)
1475                 return;
1476
1477         if (s->blockState == TBLOCK_INPROGRESS)
1478         {
1479                 /* ----------------
1480                  *      here we are in a transaction block which should commit
1481                  *      when we get to the upcoming CommitTransactionCommand()
1482                  *      so we set the state to "END".  CommitTransactionCommand()
1483                  *      will recognize this and commit the transaction and return
1484                  *      us to the default state
1485                  * ----------------
1486                  */
1487                 s->blockState = TBLOCK_END;
1488                 return;
1489         }
1490
1491         if (s->blockState == TBLOCK_ABORT)
1492         {
1493                 /* ----------------
1494                  *      here, we are in a transaction block which aborted
1495                  *      and since the AbortTransaction() was already done,
1496                  *      we do whatever is needed and change to the special
1497                  *      "END ABORT" state.      The upcoming CommitTransactionCommand()
1498                  *      will recognise this and then put us back in the default
1499                  *      state.
1500                  * ----------------
1501                  */
1502                 s->blockState = TBLOCK_ENDABORT;
1503                 return;
1504         }
1505
1506         /* ----------------
1507          *      here, the user issued COMMIT when not inside a transaction.
1508          *      Issue a notice and go to abort state.  The upcoming call to
1509          *      CommitTransactionCommand() will then put us back into the
1510          *      default state.
1511          * ----------------
1512          */
1513         elog(NOTICE, "COMMIT: no transaction in progress");
1514         AbortTransaction();
1515         s->blockState = TBLOCK_ENDABORT;
1516 }
1517
1518 /* --------------------------------
1519  *              AbortTransactionBlock
1520  * --------------------------------
1521  */
1522 #ifdef NOT_USED
1523 static void
1524 AbortTransactionBlock(void)
1525 {
1526         TransactionState s = CurrentTransactionState;
1527
1528         /* ----------------
1529          *      check the current transaction state
1530          * ----------------
1531          */
1532         if (s->state == TRANS_DISABLED)
1533                 return;
1534
1535         if (s->blockState == TBLOCK_INPROGRESS)
1536         {
1537                 /* ----------------
1538                  *      here we were inside a transaction block something
1539                  *      screwed up inside the system so we enter the abort state,
1540                  *      do the abort processing and then return.
1541                  *      We remain in the abort state until we see an
1542                  *      END TRANSACTION command.
1543                  * ----------------
1544                  */
1545                 s->blockState = TBLOCK_ABORT;
1546                 AbortTransaction();
1547                 return;
1548         }
1549
1550         /* ----------------
1551          *      here, the user issued ABORT when not inside a transaction.
1552          *      Issue a notice and go to abort state.  The upcoming call to
1553          *      CommitTransactionCommand() will then put us back into the
1554          *      default state.
1555          * ----------------
1556          */
1557         elog(NOTICE, "ROLLBACK: no transaction in progress");
1558         AbortTransaction();
1559         s->blockState = TBLOCK_ENDABORT;
1560 }
1561
1562 #endif
1563
1564 /* --------------------------------
1565  *              UserAbortTransactionBlock
1566  * --------------------------------
1567  */
1568 void
1569 UserAbortTransactionBlock()
1570 {
1571         TransactionState s = CurrentTransactionState;
1572
1573         /* ----------------
1574          *      check the current transaction state
1575          * ----------------
1576          */
1577         if (s->state == TRANS_DISABLED)
1578                 return;
1579
1580         /*
1581          * if the transaction has already been automatically aborted with an
1582          * error, and the user subsequently types 'abort', allow it.  (the
1583          * behavior is the same as if they had typed 'end'.)
1584          */
1585         if (s->blockState == TBLOCK_ABORT)
1586         {
1587                 s->blockState = TBLOCK_ENDABORT;
1588                 return;
1589         }
1590
1591         if (s->blockState == TBLOCK_INPROGRESS)
1592         {
1593                 /* ----------------
1594                  *      here we were inside a transaction block and we
1595                  *      got an abort command from the user, so we move to
1596                  *      the abort state, do the abort processing and
1597                  *      then change to the ENDABORT state so we will end up
1598                  *      in the default state after the upcoming
1599                  *      CommitTransactionCommand().
1600                  * ----------------
1601                  */
1602                 s->blockState = TBLOCK_ABORT;
1603                 AbortTransaction();
1604                 s->blockState = TBLOCK_ENDABORT;
1605                 return;
1606         }
1607
1608         /* ----------------
1609          *      here, the user issued ABORT when not inside a transaction.
1610          *      Issue a notice and go to abort state.  The upcoming call to
1611          *      CommitTransactionCommand() will then put us back into the
1612          *      default state.
1613          * ----------------
1614          */
1615         elog(NOTICE, "ROLLBACK: no transaction in progress");
1616         AbortTransaction();
1617         s->blockState = TBLOCK_ENDABORT;
1618 }
1619
1620 /* --------------------------------
1621  *              AbortOutOfAnyTransaction
1622  *
1623  * This routine is provided for error recovery purposes.  It aborts any
1624  * active transaction or transaction block, leaving the system in a known
1625  * idle state.
1626  * --------------------------------
1627  */
1628 void
1629 AbortOutOfAnyTransaction()
1630 {
1631         TransactionState s = CurrentTransactionState;
1632
1633         /*
1634          * Get out of any low-level transaction
1635          */
1636         if (s->state != TRANS_DEFAULT)
1637         {
1638                 AbortTransaction();
1639                 CleanupTransaction();
1640         }
1641
1642         /*
1643          * Now reset the high-level state
1644          */
1645         s->blockState = TBLOCK_DEFAULT;
1646 }
1647
1648 bool
1649 IsTransactionBlock()
1650 {
1651         TransactionState s = CurrentTransactionState;
1652
1653         if (s->blockState == TBLOCK_INPROGRESS
1654                 || s->blockState == TBLOCK_ABORT
1655                 || s->blockState == TBLOCK_ENDABORT)
1656                 return true;
1657
1658         return false;
1659 }