Source Code Cross Referenced for Xact.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » store » raw » xact » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.store.raw.xact 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.store.raw.xact.Xact
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to you under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.impl.store.raw.xact;
0023:
0024:        import org.apache.derby.iapi.reference.SQLState;
0025:
0026:        import org.apache.derby.iapi.store.raw.ContainerKey;
0027:
0028:        import org.apache.derby.iapi.services.context.ContextManager;
0029:        import org.apache.derby.iapi.services.daemon.Serviceable;
0030:        import org.apache.derby.iapi.services.locks.LockFactory;
0031:        import org.apache.derby.iapi.services.locks.Limit;
0032:
0033:        import org.apache.derby.iapi.store.raw.ContainerHandle;
0034:        import org.apache.derby.iapi.store.raw.Compensation;
0035:        import org.apache.derby.iapi.store.raw.GlobalTransactionId;
0036:        import org.apache.derby.iapi.store.raw.LockingPolicy;
0037:        import org.apache.derby.iapi.store.raw.Loggable;
0038:        import org.apache.derby.iapi.store.raw.RecordHandle;
0039:        import org.apache.derby.iapi.store.raw.StreamContainerHandle;
0040:        import org.apache.derby.iapi.store.raw.Transaction;
0041:
0042:        import org.apache.derby.iapi.store.raw.data.DataFactory;
0043:        import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
0044:
0045:        import org.apache.derby.iapi.store.raw.xact.RawTransaction;
0046:        import org.apache.derby.iapi.store.raw.xact.TransactionId;
0047:
0048:        import org.apache.derby.iapi.store.raw.log.LogFactory;
0049:        import org.apache.derby.iapi.store.raw.log.LogInstant;
0050:        import org.apache.derby.iapi.store.raw.log.Logger;
0051:
0052:        import org.apache.derby.iapi.store.access.FileResource;
0053:        import org.apache.derby.iapi.store.access.RowSource;
0054:        import org.apache.derby.iapi.store.access.TransactionController;
0055:        import org.apache.derby.iapi.error.ExceptionSeverity;
0056:
0057:        import org.apache.derby.iapi.services.property.PersistentSet;
0058:
0059:        import org.apache.derby.catalog.UUID;
0060:
0061:        import java.util.Stack;
0062:        import java.util.Enumeration;
0063:        import java.util.Properties;
0064:        import java.util.ArrayList;
0065:        import java.util.List;
0066:        import java.util.Dictionary;
0067:
0068:        import org.apache.derby.iapi.error.StandardException;
0069:
0070:        import org.apache.derby.iapi.services.sanity.SanityManager;
0071:        import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
0072:        import org.apache.derby.iapi.util.ByteArray;
0073:        import org.apache.derby.iapi.services.property.PropertyUtil;
0074:        import org.apache.derby.iapi.reference.Property;
0075:
0076:        import org.apache.derby.impl.store.raw.log.LogToFile;
0077:
0078:        import org.apache.derby.iapi.services.io.LimitObjectInput;
0079:
0080:        import org.apache.derby.iapi.services.context.ContextService;
0081:
0082:        /**
0083:
0084:         A transaction has five states
0085:         <OL>
0086:         <LI> CLOSED - cannot be used
0087:         <LI> IDLE - no reads have been performed by the transaction.
0088:         <LI> ACTIVE - at least one read has been attempted by the transaction
0089:         <LI> UPDATE - at least one update has been attempted by the transaction
0090:         <LI> PREPARED - the transaction is ready to commit (FUTURE).
0091:         </OL>
0092:         <BR>Transaction identifiers are re-used for transactions that do not enter the
0093:         UPDATE state during their lifetime.
0094:
0095:         @see Transaction
0096:
0097:         */
0098:        public class Xact extends RawTransaction implements  Limit {
0099:
0100:            /*
0101:             ** Static Fields
0102:             */
0103:
0104:            protected static final int CLOSED = 0;
0105:            protected static final int IDLE = 1;
0106:            protected static final int ACTIVE = 2;
0107:            protected static final int UPDATE = 3;
0108:            protected static final int PREPARED = 4;
0109:
0110:            /*
0111:             **	Transaction status stored in the beginXact and endXact
0112:             */
0113:
0114:            public static final int END_ABORTED = 0x00000001;
0115:            public static final int END_PREPARED = 0x00000002;
0116:            public static final int END_COMMITTED = 0x00000004;
0117:
0118:            public static final int RECOVERY_ROLLBACK_FIRST = 0x00000010;
0119:            public static final int INTERNAL_TRANSACTION = 0x00000020;
0120:            public static final int NESTED_TOP_TRANSACTION = 0x00000040;
0121:
0122:            /**
0123:              private static - 
0124:
0125:              make sure these bits don't overwrite bits in Transaction.commit commitflag
0126:             */
0127:            private static final int COMMIT_SYNC = 0x00010000;
0128:            private static final int COMMIT_NO_SYNC = 0x00020000;
0129:            private static final int COMMIT_PREPARE = 0x00040000;
0130:
0131:            /*
0132:             ** Fields
0133:             */
0134:
0135:            //
0136:            // set during recovery if this is the recovery transaction.  
0137:            //
0138:            private int savedEndStatus;
0139:
0140:            //
0141:            // if this transaction object was committed without syncing, then in a
0142:            // subsequent commit with sync, the log must be flushed even if the last
0143:            // transaction is read only
0144:            private boolean needSync;
0145:
0146:            //
0147:            // When the xact is first created, it is in an IDLE state.  Since the
0148:            // transaction table needs an XactId, one will be made for it.  When this
0149:            // transaction commits, it goes back to the IDLE state.  If we then create
0150:            // a new XactId for it, we will waste one XactId per transaction object
0151:            // because it must first go thru the IDLE state before it gets closed.
0152:            // Therefore, the first XactId is assigned in the constructor and
0153:            // subsequent XactId is assigned in the setActiveState.  However, the first
0154:            // time it goes into setActiveState, we don't want it to create a new
0155:            // XactId when the one that was assigned to it in the constructore is good
0156:            // enough, so we use this justCreate field to indicate to setActiveState
0157:            // whether it needs to make a new XactId (for the next transaction) for
0158:            // not. 
0159:            private boolean justCreated = true;
0160:
0161:            protected XactContext xc; // my context - set by XactContext
0162:
0163:            // these fields remain fixed for the lifetime of this object
0164:            protected final XactFactory xactFactory;
0165:            protected final DataFactory dataFactory;
0166:            protected final LogFactory logFactory;
0167:            protected final Object compatibilitySpace;
0168:
0169:            // these fields remain fixedfor the lifetime
0170:            private LockingPolicy defaultLocking;
0171:
0172:            // Global id, unique among all rawstores and all eternity
0173:            private GlobalTransactionId myGlobalId;
0174:
0175:            // id that is valid locally in this raw store.
0176:            private volatile TransactionId myId;
0177:
0178:            protected Logger logger; // the object we use to access the log.
0179:
0180:            protected volatile int state; // we access this without synchronization sometimes
0181:            private Integer inComplete = null; // set between preComplete() and postComplete()
0182:
0183:            private boolean seenUpdates; // true if this session has written a log
0184:            // record to disk.  Note this is per
0185:            // session and not per transaction, namely
0186:            // during recovery, a transaction may have
0187:            // updates but it may not have any updates
0188:            // during recovery.  In that case,
0189:            // seenUpdates is false even though state
0190:            // is UPDATE. 
0191:            // This value is used to decide whether
0192:            // the log needs to get flushed at commit
0193:            // time. 
0194:
0195:            private boolean inPostCommitProcessing; // true if we are processing post
0196:            // commit work in the same context the
0197:            // work was queued.  This is used to stop
0198:            // recursion only.  We don't want a post
0199:            // commit task to queue other post commit
0200:            // task, ad infinitum.  PostCommitWork
0201:            // requested while processing
0202:            // postCommitWork will be processed 
0203:            // by the daemon, which may itself
0204:            // recurse once.
0205:
0206:            private LogInstant logStart; // If this is a read only transaction (has
0207:            // never written a log record to disk),
0208:            // then null.  Otherwise, set to the log
0209:            // instant of the first log record.
0210:
0211:            private LogInstant logLast; // the last log record written by this
0212:            // transaction 
0213:
0214:            private Stack savePoints; // stack of SavePoint objects.
0215:
0216:            protected List postCommitWorks; // a list of post commit work
0217:            protected List postTerminationWorks; // work to be done after
0218:            // transaction terminates,
0219:            // commit or abort
0220:            private boolean recoveryTransaction; // this transaction is being
0221:            // used by recovery
0222:
0223:            DynamicByteArrayOutputStream logBuffer;
0224:
0225:            private boolean postCompleteMode; // perform most preComplete work in postComplete
0226:
0227:            // Use this flag to catch the case where a global transaction was closed.
0228:            // Normally a closed transaction should not be aborted again, but we need
0229:            // to allow abort of a closed global transaction for error handling.  Use
0230:            // this flag to make sure people are not abusing this loop hole.
0231:            // RESOLVE: sku to remove before GA
0232:            private boolean sanityCheck_xaclosed;
0233:
0234:            // Indicates the name of the transaction, and if it is set, it is displayed
0235:            // by the transactiontable VTI
0236:            private String transName;
0237:
0238:            // The transaction is only allowed read operations, no log writes.
0239:            private boolean readOnly;
0240:
0241:            // true, if the transaction executed some operations(like unlogged
0242:            // operations) that block the  online backup to prevent inconsistent
0243:            // backup copy.
0244:            private boolean backupBlocked;
0245:
0246:            /*
0247:             ** Constructor
0248:             */
0249:
0250:            protected Xact(XactFactory xactFactory, LogFactory logFactory,
0251:                    DataFactory dataFactory, boolean readOnly,
0252:                    Object compatibilitySpace) {
0253:
0254:                super ();
0255:
0256:                this .xactFactory = xactFactory;
0257:                this .logFactory = logFactory;
0258:                this .dataFactory = dataFactory;
0259:                this .readOnly = readOnly;
0260:
0261:                this .compatibilitySpace = (compatibilitySpace == null ? this 
0262:                        : compatibilitySpace);
0263:
0264:                if (SanityManager.DEBUG) {
0265:                    SanityManager.ASSERT(dataFactory != null,
0266:                            "datafactory is null");
0267:                    SanityManager.ASSERT(xactFactory != null,
0268:                            "xactfactory is null");
0269:                    SanityManager.ASSERT(logFactory != null,
0270:                            "logfactory is null");
0271:                }
0272:
0273:                resetDefaultLocking();
0274:
0275:                // TransactionTable needs this
0276:                xactFactory.setNewTransactionId((XactId) null, this );
0277:
0278:                setIdleState();
0279:
0280:                backupBlocked = false;
0281:
0282:                /*
0283:                System.out.println("Xact.constructor: readonly = " + this.readOnly +
0284:                        ";this = " + this);
0285:                 */
0286:            }
0287:
0288:            /*
0289:             ** Methods of RawTransaction
0290:             */
0291:
0292:            /**
0293:             */
0294:            public final LockFactory getLockFactory() {
0295:                return xactFactory.getLockFactory();
0296:            }
0297:
0298:            public final DataFactory getDataFactory() {
0299:                return dataFactory;
0300:            }
0301:
0302:            /**
0303:            	Get cache statistics for the specified cache
0304:             */
0305:            public long[] getCacheStats(String cacheName) {
0306:                return getDataFactory().getCacheStats(cacheName);
0307:            }
0308:
0309:            /**
0310:            	Reset the cache statistics for the specified cache
0311:             */
0312:            public void resetCacheStats(String cacheName) {
0313:                getDataFactory().resetCacheStats(cacheName);
0314:            }
0315:
0316:            /**
0317:            	Return true if any transaction is currently blocked, even if not by
0318:            	this transaction.
0319:
0320:             */
0321:            public boolean anyoneBlocked() {
0322:                return getLockFactory().anyoneBlocked();
0323:            }
0324:
0325:            public DynamicByteArrayOutputStream getLogBuffer() {
0326:
0327:                if (logBuffer == null) {
0328:                    logBuffer = new DynamicByteArrayOutputStream(1024);
0329:                } else {
0330:                    logBuffer.reset();
0331:                }
0332:
0333:                return logBuffer;
0334:            }
0335:
0336:            /** Log and apply a compensation operation.
0337:            	Only need to write out the compensation op itself, the optional data has already
0338:            	been written by the rollforward operation this is attempting to undo.
0339:
0340:            	@see RawTransaction#logAndDo 
0341:            	
0342:            	@exception StandardException  Standard cloudscape exception policy
0343:             */
0344:            public void logAndUndo(Compensation compensation,
0345:                    LogInstant undoInstant, LimitObjectInput in)
0346:                    throws StandardException {
0347:                if (SanityManager.DEBUG) {
0348:                    SanityManager.ASSERT(logStart != null);
0349:                }
0350:
0351:                setActiveState();
0352:
0353:                if (state == ACTIVE)
0354:                    setUpdateState();
0355:
0356:                seenUpdates = true;
0357:
0358:                LogInstant clrInstant = logger.logAndUndo(this , compensation,
0359:                        undoInstant, in);
0360:
0361:                setLastLogInstant(clrInstant);
0362:
0363:                // set the top savepoint to rollback to this record if it doesn't yet have a point saved
0364:                if ((savePoints != null) && !savePoints.empty()) {
0365:
0366:                    SavePoint sp = (SavePoint) savePoints.peek();
0367:                    if (sp.getSavePoint() == null)
0368:                        sp.setSavePoint(clrInstant);
0369:                }
0370:            }
0371:
0372:            /** 
0373:            	Add this to the xactFactory list of update transaction.
0374:             */
0375:            public void addUpdateTransaction(int transactionStatus) {
0376:                // during runtime, rollbackFirst == recoveryRolblackFirst(), but during
0377:                // recovery redo, we only use a regular transaction, so we need to get
0378:                // the rollbackFirst status from the log record
0379:                //
0380:                // If my Id is null, I have no identity, makes no sense to add it to a
0381:                // transaction table where my identity will be saved and restored
0382:                if (myId != null)
0383:                    xactFactory.addUpdateTransaction(myId, this ,
0384:                            transactionStatus);
0385:
0386:            }
0387:
0388:            /** Remove this from the xactFactory list of update transaction. */
0389:            public void removeUpdateTransaction() {
0390:                if (myId != null)
0391:                    xactFactory.removeUpdateTransaction(myId);
0392:
0393:                // If my Id is null, I have no identity, makes no sense to remove it
0394:                // from transaction table
0395:            }
0396:
0397:            /** Remove this from the xactFactory list of update transaction. */
0398:            public void prepareTransaction() {
0399:                // RESOLVE - should I be changing the state to PREPARE?
0400:
0401:                if (myId != null) {
0402:                    // If my Id is null, I have no identity, makes no sense to set
0403:                    // my state in the transaction table.
0404:
0405:                    xactFactory.prepareTransaction(myId);
0406:                }
0407:            }
0408:
0409:            /**
0410:            	Set the log instant for the first log record written by this transaction.
0411:             */
0412:            public void setFirstLogInstant(LogInstant instant) {
0413:                if (SanityManager.DEBUG) {
0414:                    SanityManager.ASSERT(instant != null);
0415:                    SanityManager.ASSERT(logStart == null);
0416:                }
0417:
0418:                logStart = instant;
0419:            }
0420:
0421:            /**
0422:            	Get the log instant for the first log record written by this transaction.
0423:             */
0424:            public LogInstant getFirstLogInstant() {
0425:                return logStart;
0426:            }
0427:
0428:            /**
0429:            	Set the log instant for the last log record written by this transaction. 
0430:             */
0431:            public void setLastLogInstant(LogInstant instant) {
0432:                if (SanityManager.DEBUG) {
0433:                    SanityManager.ASSERT(instant != null);
0434:                }
0435:
0436:                logLast = instant;
0437:            }
0438:
0439:            /**
0440:            	Get the log instant for the last log record written by this transaction. 
0441:             */
0442:            public LogInstant getLastLogInstant() {
0443:                return logLast;
0444:            }
0445:
0446:            /**
0447:            	Set my transaction identifier.
0448:             */
0449:            public void setTransactionId(GlobalTransactionId extid,
0450:                    TransactionId localid) {
0451:
0452:                if (SanityManager.DEBUG) {
0453:
0454:                    //SanityManager.ASSERT(myGlobalId == null, "my globalId is not null");
0455:                    if (!(state == IDLE || state == Xact.ACTIVE || (state == CLOSED && justCreated))) {
0456:                        SanityManager
0457:                                .THROWASSERT("my state is not idle nor active "
0458:                                        + state);
0459:                    }
0460:                }
0461:
0462:                myGlobalId = extid;
0463:                myId = localid;
0464:
0465:                if (SanityManager.DEBUG) {
0466:                    if (SanityManager.DEBUG_ON("XATrace") && extid != null) {
0467:                        SanityManager.DEBUG("XATrace", "setting xid: " + myId
0468:                                + " " + myGlobalId + " state " + state + " "
0469:                                + this );
0470:
0471:                        SanityManager.showTrace(new Throwable());
0472:                        // Thread.dumpStack();
0473:                    }
0474:                }
0475:
0476:            }
0477:
0478:            public void setTransactionId(Loggable beginXact,
0479:                    TransactionId localId) {
0480:                if (SanityManager.DEBUG) {
0481:                    // SanityManager.ASSERT(myId == null);
0482:                    SanityManager.ASSERT((state == IDLE) || (state == ACTIVE));
0483:                    SanityManager.ASSERT(beginXact instanceof  BeginXact);
0484:                }
0485:
0486:                myId = localId;
0487:                myGlobalId = ((BeginXact) beginXact).getGlobalId();
0488:            }
0489:
0490:            /*
0491:             ** Methods of Transaction
0492:             */
0493:
0494:            /**
0495:            	The default value for LOCKS_ESCALATION_THRESHOLD
0496:            	@exception StandardException  Standard cloudscape exception policy
0497:             */
0498:            public void setup(PersistentSet set) throws StandardException {
0499:
0500:                int escalationThreshold = PropertyUtil.getServiceInt(set,
0501:                        Property.LOCKS_ESCALATION_THRESHOLD,
0502:                        Property.MIN_LOCKS_ESCALATION_THRESHOLD,
0503:                        Integer.MAX_VALUE,
0504:                        Property.DEFAULT_LOCKS_ESCALATION_THRESHOLD);
0505:
0506:                getLockFactory()
0507:                        .setLimit(this , this , escalationThreshold, this );
0508:
0509:            }
0510:
0511:            /**
0512:            	get the Global (external to raw store) transaction id that is unique
0513:            	across all raw stores
0514:             */
0515:            public final GlobalTransactionId getGlobalId() {
0516:
0517:                return myGlobalId;
0518:            }
0519:
0520:            public final ContextManager getContextManager() {
0521:                return (xc.getContextManager());
0522:            }
0523:
0524:            /**
0525:             * Get the compatibility space of the transaction.
0526:             * <p>
0527:             * Returns an object that can be used with the lock manager to provide
0528:             * the compatibility space of a transaction.  2 transactions with the
0529:             * same compatibility space will not conflict in locks.  The usual case
0530:             * is that each transaction has it's own unique compatibility space.
0531:             * <p>
0532:             *
0533:             * @return The compatibility space of the transaction.
0534:             **/
0535:            public Object getCompatibilitySpace() {
0536:                if (SanityManager.DEBUG) {
0537:                    SanityManager.ASSERT(compatibilitySpace != null,
0538:                            "cannot have a null compatibilitySpace.");
0539:                }
0540:
0541:                return (this .compatibilitySpace);
0542:            }
0543:
0544:            /**
0545:            	get the short (internal to raw store) transaction id that is unique
0546:            	only for this raw store
0547:             */
0548:            public final TransactionId getId() {
0549:
0550:                if (SanityManager.DEBUG)
0551:                    SanityManager.ASSERT(myId != null,
0552:                            "cannot have a transaction with null id");
0553:
0554:                return myId;
0555:            }
0556:
0557:            /**
0558:            	Get the transaction id without sanity check, this should only be called
0559:            	by a cloned TransactionTableEntry 
0560:             */
0561:            protected final TransactionId getIdNoCheck() {
0562:                return myId;
0563:            }
0564:
0565:            /**
0566:            	Get my transaction context Id
0567:             */
0568:            public final String getContextId() {
0569:                return (xc == null) ? null : xc.getIdName();
0570:            }
0571:
0572:            /**
0573:            	Get the current default locking policy for all operations within this
0574:            	transaction. The transaction is initially started with a default
0575:            	locking policy equivalent to
0576:            	<PRE>
0577:            		 newLockingPolicy(
0578:                      LockingPolicy.MODE_RECORD, TransactionController.ISOLATION_SERIALIZABLE, true);
0579:            	</PRE>
0580:                This default can be changed by subsequent calls to 
0581:                setDefaultLockingPolicy(LockingPolicy policy).
0582:
0583:                @see Transaction#getDefaultLockingPolicy
0584:
0585:
0586:            	@return The current default locking policy in this transaction.
0587:             */
0588:
0589:            public LockingPolicy getDefaultLockingPolicy() {
0590:                return (defaultLocking);
0591:            }
0592:
0593:            /** @see Transaction#newLockingPolicy */
0594:            public final LockingPolicy newLockingPolicy(int mode,
0595:                    int isolation, boolean stricterOk) {
0596:
0597:                return xactFactory
0598:                        .getLockingPolicy(mode, isolation, stricterOk);
0599:
0600:            }
0601:
0602:            /** @see Transaction#setDefaultLockingPolicy */
0603:            public final void setDefaultLockingPolicy(LockingPolicy policy) {
0604:
0605:                if (policy == null)
0606:                    policy = xactFactory.getLockingPolicy(
0607:                            LockingPolicy.MODE_NONE,
0608:                            TransactionController.ISOLATION_NOLOCK, false);
0609:                defaultLocking = policy;
0610:            }
0611:
0612:            /** 
0613:              @exception StandardException  Standard cloudscape exception policy
0614:             */
0615:            public LogInstant commit() throws StandardException {
0616:                return commit(COMMIT_SYNC);
0617:            }
0618:
0619:            /** 
0620:              @exception StandardException  Standard cloudscape exception policy
0621:             */
0622:            public LogInstant commitNoSync(int commitflag)
0623:                    throws StandardException {
0624:                if (SanityManager.DEBUG) {
0625:                    int checkflag = Transaction.RELEASE_LOCKS
0626:                            | Transaction.KEEP_LOCKS;
0627:
0628:                    SanityManager
0629:                            .ASSERT((commitflag & checkflag) != 0,
0630:                                    "commitNoSync must specify whether to keep or release locks");
0631:
0632:                    SanityManager.ASSERT((commitflag & checkflag) != checkflag,
0633:                            "cannot set both RELEASE and KEEP LOCKS flag");
0634:
0635:                    if ((commitflag & TransactionController.READONLY_TRANSACTION_INITIALIZATION) != 0) {
0636:                        SanityManager.ASSERT((state == IDLE)
0637:                                || (state == ACTIVE));
0638:                    }
0639:                }
0640:
0641:                // Short circuit commit no sync if we are still initializing the
0642:                // transaction.  Before a new transaction object is returned to the
0643:                // user, it is "commit'ed" many times using commitNoSync with 
0644:                // TransactionController.READONLY_TRANSACTION_INITIALIZATION flag to
0645:                // release read locks and reset the transaction state back to Idle.  
0646:                // If nothing has actually happened to the transaction object, return
0647:                // right away and avoid the cost of going thru the commit logic.
0648:                //
0649:                if (state == IDLE
0650:                        && savePoints == null
0651:                        && ((commitflag & TransactionController.READONLY_TRANSACTION_INITIALIZATION) != 0))
0652:                    return null;
0653:
0654:                return commit(COMMIT_NO_SYNC | commitflag);
0655:            }
0656:
0657:            /** 
0658:              @exception StandardException  Standard cloudscape exception policy
0659:              @see Transaction#commit
0660:             */
0661:
0662:            /**
0663:             * Do work of commit that is common to xa_prepare and commit.
0664:             * <p>
0665:             * Do all the work necessary as part of a commit up to and including
0666:             * writing the commit log record.  This routine is used by both prepare
0667:             * and commit.  The work post commit is done by completeCommit().
0668:             * <p>
0669:             *
0670:             * @param commitflag various flavors of commit.
0671:             *
0672:             * @exception  StandardException  Standard exception policy.
0673:             * @see Transaction#commit
0674:             **/
0675:            private LogInstant prepareCommit(int commitflag)
0676:                    throws StandardException {
0677:                LogInstant flushTo = null;
0678:
0679:                if (state == CLOSED) {
0680:                    throw StandardException
0681:                            .newException(SQLState.XACT_PROTOCOL_VIOLATION);
0682:                }
0683:
0684:                if (SanityManager.DEBUG) {
0685:                    if ((commitflag & Transaction.KEEP_LOCKS) != 0) {
0686:                        // RESOLVE (mikem) - prepare actually want's to keep locks
0687:                        // during a prepare.
0688:                        SanityManager
0689:                                .ASSERT(
0690:                                        (((commitflag & COMMIT_NO_SYNC) != 0) || ((commitflag & COMMIT_PREPARE) != 0)),
0691:                                        "can keep locks around only in commitNoSync or prepare");
0692:
0693:                        SanityManager
0694:                                .ASSERT(isUserTransaction(),
0695:                                        "KEEP_LOCKS can only be set on user transaction commits");
0696:                    }
0697:                }
0698:
0699:                try {
0700:
0701:                    preComplete(COMMIT);
0702:
0703:                    // flush the log.
0704:
0705:                    if (seenUpdates) {
0706:
0707:                        EndXact ex = new EndXact(
0708:                                getGlobalId(),
0709:                                ((commitflag & COMMIT_PREPARE) == 0 ? END_COMMITTED
0710:                                        : END_PREPARED)
0711:                                        | statusForEndXactLog());
0712:
0713:                        flushTo = logger.logAndDo(this , ex);
0714:
0715:                        if (xactFactory.flushLogOnCommit(xc.getIdName())) {
0716:                            if ((commitflag & COMMIT_SYNC) == 0) {
0717:                                // not flushing the log right now, subsequent commit
0718:                                // will need to flush the log
0719:                                needSync = true;
0720:                            } else {
0721:                                logger.flush(flushTo);
0722:                                needSync = false;
0723:                            }
0724:                        }
0725:                    } else if (needSync && (commitflag & COMMIT_SYNC) != 0) {
0726:                        // this transaction object was used to lazily commit some
0727:                        // previous transaction without syncing.  Now that we commit
0728:                        // for real, make sure any outstanding log is flushed.
0729:                        logger.flushAll();
0730:                        needSync = false;
0731:                    }
0732:                } catch (StandardException se) {
0733:
0734:                    // This catches any exceptions that have Transaction severity
0735:                    // or less (e.g. Statement exception). If we received any lesser
0736:                    // error then we abort the transaction anyway.
0737:
0738:                    if (se.getSeverity() < ExceptionSeverity.TRANSACTION_SEVERITY) {
0739:                        throw StandardException.newException(
0740:                                SQLState.XACT_COMMIT_EXCEPTION, se);
0741:                    }
0742:
0743:                    throw se;
0744:
0745:                }
0746:                return flushTo;
0747:            }
0748:
0749:            /**
0750:             * Do work to complete a commit which is not just a prepare.
0751:             * <p>
0752:             * Releases locks, does post commit work, and moves the state of the
0753:             * transaction to IDLE.
0754:             * <p>
0755:             *
0756:             * @param commitflag various flavors of commit.
0757:             *
0758:             * @exception  StandardException  Standard exception policy.
0759:             **/
0760:            private void completeCommit(int commitflag)
0761:                    throws StandardException {
0762:                // this releases our logical locks if commitflag don't have KEEP_LOCKS.
0763:                postComplete(commitflag, COMMIT);
0764:
0765:                // this transfer postCommitWorks to PostCommit queue
0766:                if ((commitflag & Transaction.KEEP_LOCKS) == 0) {
0767:                    // if locks are released, start post commit processing
0768:                    postTermination();
0769:                } else {
0770:                    // RESOLVE: actually, this transaction may not have outstanding
0771:                    // locks.  It didn't release them, but that doesn't mean it has got
0772:                    // them.  This is mostly harmless.
0773:
0774:                    if (SanityManager.DEBUG)
0775:                        SanityManager
0776:                                .ASSERT(myGlobalId == null,
0777:                                        "calling commit with KEEP_LOCKS on a global transaction");
0778:
0779:                    // we have unreleased locks, the transaction has resource and
0780:                    // therefore is "active"
0781:                    setActiveState();
0782:                }
0783:
0784:                myGlobalId = null;
0785:                return;
0786:            }
0787:
0788:            /** 
0789:              @exception StandardException  Standard cloudscape exception policy
0790:              @see Transaction#commit
0791:             */
0792:            private LogInstant commit(int commitflag) throws StandardException {
0793:                if (SanityManager.DEBUG) {
0794:                    if (SanityManager.DEBUG_ON("XATrace"))
0795:                        SanityManager.DEBUG("XATrace", "commiting ");
0796:                }
0797:
0798:                LogInstant flushTo = prepareCommit(commitflag);
0799:
0800:                completeCommit(commitflag);
0801:
0802:                return (flushTo);
0803:            }
0804:
0805:            /** 
0806:                @exception StandardException  Standard cloudscape exception policy
0807:            	@see Transaction#abort
0808:             */
0809:            public void abort() throws StandardException {
0810:
0811:                if (SanityManager.DEBUG) {
0812:                    if (SanityManager.DEBUG_ON("XATrace"))
0813:                        SanityManager.DEBUG("XATrace", "aborting ");
0814:                }
0815:
0816:                if (state == CLOSED) {
0817:                    // I would have leave this in but close() nulls out myGlobalId
0818:                    // if (myGlobalId == null)
0819:                    // {
0820:                    //   throw StandardException.newException(
0821:                    //           SQLState.XACT_PROTOCOL_VIOLATION);
0822:                    // }
0823:
0824:                    if (SanityManager.DEBUG) {
0825:                        // Only global transaction is allowed to abort a closed
0826:                        // transaction.
0827:                        if (!sanityCheck_xaclosed) {
0828:                            throw StandardException
0829:                                    .newException(SQLState.XACT_PROTOCOL_VIOLATION);
0830:                        }
0831:                    }
0832:
0833:                    // In global transaction, the xact object is closed automatically
0834:                    // on a transaction level rollback.  This cause error handling to
0835:                    // fail because when upper level contexts in the context manager
0836:                    // unwinds, it calls abort again, which would have caused a
0837:                    // protocol violation.
0838:                    return;
0839:                }
0840:
0841:                /* This routine is never called by recovery redo, only by runtime and
0842:                   recovery undo. During recovery undo, even though no log record has
0843:                   been written by this session, it still need to rollback the
0844:                   incomplete transaction.
0845:
0846:                   The way to tell if this trasanction has ever written a log record is
0847:                   by FirstLogInstant.
0848:                 */
0849:
0850:                try {
0851:                    preComplete(ABORT);
0852:
0853:                    // rollback the log - if logger is null, nothing I can do, crash.
0854:                    if (getFirstLogInstant() != null) {
0855:                        if (logger == null) {
0856:                            throw StandardException
0857:                                    .newException(SQLState.XACT_CANNOT_ABORT_NULL_LOGGER);
0858:                        }
0859:
0860:                        logger.undo(this , getId(), getFirstLogInstant(),
0861:                                getLastLogInstant());
0862:
0863:                        EndXact ex = new EndXact(getGlobalId(), END_ABORTED
0864:                                | statusForEndXactLog());
0865:
0866:                        logger.flush(logger.logAndDo(this , ex));
0867:                    } else if (needSync) {
0868:                        // this transaction object was used to lazily commit some
0869:                        // previous transaction without syncing.  Now that we abort
0870:                        // for real, make sure any outstanding log is flushed.
0871:                        logger.flushAll();
0872:                    }
0873:
0874:                    needSync = false;
0875:
0876:                } catch (StandardException se) {
0877:
0878:                    // This catches any exceptions that have System severity
0879:                    // or less (e.g. Statement exception).
0880:                    //
0881:                    // If we have any error during an undo we just shut the system
0882:                    // down, this is a bit drastic but it does ensure that the database
0883:                    // will not become corrupted by changes that see half committed 
0884:                    // changes.
0885:                    //
0886:                    // Note that we do not release our locks if we come thorugh this
0887:                    // path, if we did then another transaction could complete before
0888:                    // the system shuts down and make changes based upon the changes
0889:                    // that we couldn't back out.
0890:
0891:                    if (se.getSeverity() < ExceptionSeverity.SYSTEM_SEVERITY) {
0892:                        throw logFactory
0893:                                .markCorrupt(StandardException.newException(
0894:                                        SQLState.XACT_ABORT_EXCEPTION, se));
0895:                    }
0896:
0897:                    throw se;
0898:
0899:                }
0900:
0901:                // this releases our locks.
0902:                postComplete(0, ABORT);
0903:
0904:                // get rid of all post commit work - we aborted, therefore no post
0905:                // commit work
0906:                if (postCommitWorks != null && !postCommitWorks.isEmpty()) {
0907:                    postCommitWorks.clear();
0908:                }
0909:
0910:                // Now do post termination work - must do this after the rollback is
0911:                // complete because the rollback itself may generate postTermination
0912:                // work.
0913:                postTermination();
0914:
0915:                myGlobalId = null;
0916:            }
0917:
0918:            /**
0919:             * During recovery re-prepare a transaction.
0920:             * <p>
0921:             * After redo() and undo(), this routine is called on all outstanding 
0922:             * in-doubt (prepared) transactions.  This routine re-acquires all 
0923:             * logical write locks for operations in the xact, and then modifies
0924:             * the transaction table entry to make the transaction look as if it
0925:             * had just been prepared following startup after recovery.
0926:             * <p>
0927:             * This routine is only called during Recovery.
0928:             *
0929:             * @exception  StandardException  Standard exception policy.
0930:             **/
0931:            public void reprepare() throws StandardException {
0932:                if (state == CLOSED) {
0933:                    throw StandardException
0934:                            .newException(SQLState.XACT_PROTOCOL_VIOLATION);
0935:                }
0936:
0937:                // Should only be called during recovery on global transactions, 
0938:                // after redo and undo.
0939:                if (SanityManager.DEBUG) {
0940:                    SanityManager.ASSERT(myGlobalId != null);
0941:                    SanityManager.ASSERT(state == PREPARED);
0942:                }
0943:
0944:                try {
0945:                    if (logger == null) {
0946:                        throw StandardException
0947:                                .newException(SQLState.XACT_CANNOT_ABORT_NULL_LOGGER);
0948:                    }
0949:
0950:                    // temporarily set state back to UPDATE, so that the reprepare()
0951:                    // call can do operations on the xact that would "normally" be 
0952:                    // disallowed on a prepared xact - like opening a container to
0953:                    // lock it.
0954:
0955:                    state = UPDATE;
0956:
0957:                    // re-prepare the transaction.
0958:                    logger.reprepare(this , getId(), getFirstLogInstant(),
0959:                            getLastLogInstant());
0960:
0961:                    // make sure the xact is prepare state when we are done.
0962:                    state = PREPARED;
0963:
0964:                    seenUpdates = true;
0965:
0966:                } catch (StandardException se) {
0967:
0968:                    // This catches any exceptions that have System severity
0969:                    // or less (e.g. Statement exception).
0970:                    //
0971:                    // If we have any error during an reprepare we just shut the system
0972:                    // down, this is a bit drastic but it does ensure that the database
0973:                    // will not become corrupted by changes that see data that is part
0974:                    // of a prepared transaction.
0975:                    //
0976:                    // Note that we do not release our locks if we come thorugh this
0977:                    // path, if we did then another transaction could complete before
0978:                    // the system shuts down and make changes based upon the changes
0979:                    // that we couldn't back out.
0980:
0981:                    if (se.getSeverity() < ExceptionSeverity.SYSTEM_SEVERITY) {
0982:                        throw logFactory
0983:                                .markCorrupt(StandardException.newException(
0984:                                        SQLState.XACT_ABORT_EXCEPTION, se));
0985:                    }
0986:
0987:                    throw se;
0988:                }
0989:
0990:                // RESOLVE - something needs to change the state of the XACT so that
0991:                // it is not recovery state anymore?
0992:            }
0993:
0994:            /**
0995:                If this transaction is not idle, abort it.  After this call close().
0996:
0997:            	@exception StandardException Standard Cloudscape error policy
0998:                Thrown if the transaction is not idle.
0999:
1000:            	
1001:             */
1002:            public void destroy() throws StandardException {
1003:                if (state != CLOSED)
1004:                    abort();
1005:
1006:                close();
1007:            }
1008:
1009:            /**
1010:                @exception StandardException  Standard cloudscape exception policy
1011:            	@exception StandardException Thrown if the transaction is not idle, the
1012:            	transaction remains open.
1013:            	@see Transaction#close
1014:
1015:            	@exception StandardException	Standard cloudscape policy
1016:             */
1017:            public void close() throws StandardException {
1018:
1019:                /*
1020:
1021:                if (((LogToFile) logFactory).inRedo)
1022:                {
1023:                    SanityManager.showTrace(new Throwable());
1024:                    SanityManager.THROWASSERT("in Redo while in close");
1025:                }
1026:                 */
1027:
1028:                switch (state) {
1029:                case CLOSED:
1030:                    return;
1031:                case IDLE:
1032:                    break;
1033:                default:
1034:                    throw StandardException
1035:                            .newException(SQLState.XACT_TRANSACTION_NOT_IDLE);
1036:                }
1037:
1038:                if (SanityManager.DEBUG) {
1039:
1040:                    SanityManager.ASSERT(xc.getTransaction() == this );
1041:
1042:                    SanityManager
1043:                            .ASSERT((postCommitWorks == null || postCommitWorks
1044:                                    .isEmpty()),
1045:                                    "cannot close a transaction with post commit work pending");
1046:
1047:                    // use this for sanity checking
1048:                    if (myGlobalId != null)
1049:                        sanityCheck_xaclosed = true;
1050:                }
1051:
1052:                getLockFactory().clearLimit(this , this );
1053:
1054:                if (SanityManager.DEBUG) {
1055:                    if (SanityManager.DEBUG_ON("XATrace"))
1056:                        SanityManager.DEBUG("XATrace", "closing " + myId + " "
1057:                                + myGlobalId);
1058:                    // Thread.dumpStack();
1059:                }
1060:
1061:                // if we just finished recovery myId could be null
1062:                if (myId != null)
1063:                    xactFactory.remove((XactId) myId);
1064:
1065:                xc.popMe();
1066:                xc = null;
1067:
1068:                myGlobalId = null;
1069:                myId = null;
1070:                logStart = null;
1071:                logLast = null;
1072:
1073:                /* MT - no need to synchronize it, the state is current IDLE which will
1074:                 * return the same result to isActive() as if it is CLOSED
1075:                 */
1076:                state = CLOSED;
1077:
1078:            }
1079:
1080:            /** 
1081:            	Log the operation and do it.
1082:
1083:            	If this transaction has not generated any log records prior to this,
1084:            	then log a beginXact log record.
1085:
1086:            	If the passed in operation is null, then do nothing (after logging the
1087:            	beginXact if needed).
1088:
1089:                @exception StandardException  Standard cloudscape exception policy
1090:            	@see Transaction#logAndDo 
1091:             */
1092:            public void logAndDo(Loggable operation) throws StandardException {
1093:
1094:                LogInstant instant = null;
1095:
1096:                if (logger == null)
1097:                    getLogger();
1098:
1099:                if (logger == null) {
1100:                    throw StandardException
1101:                            .newException(SQLState.XACT_CANNOT_LOG_CHANGE);
1102:                }
1103:
1104:                setActiveState();
1105:
1106:                if (state == ACTIVE) {
1107:                    instant = logger.logAndDo(this , new BeginXact(
1108:                            getGlobalId(), statusForBeginXactLog()));
1109:
1110:                    setUpdateState();
1111:                }
1112:                seenUpdates = true;
1113:
1114:                if (operation != null) {
1115:                    instant = logger.logAndDo(this , operation);
1116:                    if (instant != null) {
1117:                        setLastLogInstant(instant);
1118:
1119:                        if ((savePoints != null) && !savePoints.empty()) {
1120:                            for (int i = savePoints.size() - 1; i >= 0; i--) {
1121:                                // set the top savepoint to rollback to this record if
1122:                                // it doesn't yet have a point saved
1123:
1124:                                SavePoint sp = (SavePoint) savePoints
1125:                                        .elementAt(i);
1126:                                if (sp.getSavePoint() == null) {
1127:                                    sp.setSavePoint(instant);
1128:                                } else
1129:                                    break;
1130:                            }
1131:                        }
1132:                    }
1133:
1134:                } else {
1135:                    if (instant != null)
1136:                        setLastLogInstant(instant);
1137:                }
1138:
1139:            }
1140:
1141:            public void addPostCommitWork(Serviceable work) {
1142:                if (recoveryTransaction)
1143:                    return;
1144:
1145:                if (postCommitWorks == null)
1146:                    postCommitWorks = new ArrayList(1);
1147:                postCommitWorks.add(work);
1148:            }
1149:
1150:            public void addPostTerminationWork(Serviceable work) {
1151:                if (recoveryTransaction)
1152:                    return;
1153:
1154:                if (postTerminationWorks == null)
1155:                    postTerminationWorks = new ArrayList(2);
1156:                postTerminationWorks.add(work);
1157:            }
1158:
1159:            /**
1160:            	Return a record handle that is initialized to the given page number and
1161:                record id.
1162:
1163:            	@exception StandardException Standard cloudscape exception policy.
1164:
1165:            	@param segmentId    segment where the RecordHandle belongs.
1166:            	@param containerId  container where the RecordHandle belongs.
1167:            	@param pageNumber   the page number of the RecordHandle.
1168:            	@param recordId     the record id of the RecordHandle.
1169:
1170:            	@see RecordHandle
1171:             */
1172:            //	public RecordHandle makeRecordHandle(long segmentId, long containerId, long pageNumber, int recordId)
1173:            //		 throws	StandardException
1174:            //    {
1175:            //         return(this.dataFactory.makeRecordHandle(
1176:            //             segmentId, containerId, pageNumber, recordId));
1177:            //     }
1178:            /** 
1179:                @exception StandardException  Standard cloudscape exception policy
1180:            	@see Transaction#openContainer 
1181:             */
1182:            public ContainerHandle openContainer(ContainerKey containerId,
1183:                    int mode) throws StandardException {
1184:
1185:                return openContainer(containerId, defaultLockingPolicy(), mode);
1186:            }
1187:
1188:            /** 
1189:                @exception StandardException  Standard cloudscape exception policy
1190:            	@see Transaction#openContainer 
1191:             */
1192:            public ContainerHandle openContainer(ContainerKey containerId,
1193:                    LockingPolicy locking, int mode) throws StandardException {
1194:
1195:                setActiveState();
1196:
1197:                if (locking == null)
1198:                    locking = xactFactory.getLockingPolicy(
1199:                            LockingPolicy.MODE_NONE,
1200:                            TransactionController.ISOLATION_NOLOCK, false);
1201:
1202:                return dataFactory.openContainer(this , containerId, locking,
1203:                        mode);
1204:            }
1205:
1206:            /**
1207:            	Open a container that may already have been dropped.
1208:
1209:            	@exception StandardException  Standard cloudscape exception policy
1210:            	@see RawTransaction#openDroppedContainer
1211:             */
1212:            public RawContainerHandle openDroppedContainer(
1213:                    ContainerKey containerId, LockingPolicy locking)
1214:                    throws StandardException {
1215:                setActiveState();
1216:
1217:                if (locking == null)
1218:                    locking = xactFactory.getLockingPolicy(
1219:                            LockingPolicy.MODE_NONE,
1220:                            TransactionController.ISOLATION_NOLOCK, false);
1221:
1222:                RawContainerHandle hdl = null;
1223:
1224:                // first try to open it for update, if that fail, open it for read
1225:                try {
1226:                    hdl = dataFactory.openDroppedContainer(this , containerId,
1227:                            locking, ContainerHandle.MODE_FORUPDATE);
1228:                } catch (StandardException se) {
1229:                    // if this also fail, throw exception
1230:                    hdl = dataFactory.openDroppedContainer(this , containerId,
1231:                            locking, ContainerHandle.MODE_READONLY);
1232:                }
1233:
1234:                return hdl;
1235:            }
1236:
1237:            /** 
1238:                @exception StandardException  Standard cloudscape exception policy
1239:            	@see Transaction#addContainer 
1240:             */
1241:            public long addContainer(long segmentId, long containerid,
1242:                    int mode, Properties tableProperties, int temporaryFlag)
1243:                    throws StandardException {
1244:
1245:                setActiveState();
1246:
1247:                return dataFactory.addContainer(this , segmentId, containerid,
1248:                        mode, tableProperties, temporaryFlag);
1249:            }
1250:
1251:            /** 
1252:                @exception StandardException  Standard cloudscape exception policy
1253:            	@see Transaction#addAndLoadStreamContainer
1254:             */
1255:            public long addAndLoadStreamContainer(long segmentId,
1256:                    Properties tableProperties, RowSource rowSource)
1257:                    throws StandardException {
1258:
1259:                setActiveState();
1260:
1261:                return dataFactory.addAndLoadStreamContainer(this , segmentId,
1262:                        tableProperties, rowSource);
1263:
1264:            }
1265:
1266:            /** 
1267:                @exception StandardException  Standard cloudscape exception policy
1268:            	@see Transaction#openStreamContainer
1269:             */
1270:            public StreamContainerHandle openStreamContainer(long segmentId,
1271:                    long containerId, boolean hold) throws StandardException {
1272:                setActiveState();
1273:
1274:                return (dataFactory.openStreamContainer(this , segmentId,
1275:                        containerId, hold));
1276:            }
1277:
1278:            /**
1279:            	@see Transaction#dropStreamContainer
1280:            	@exception StandardException Standard Cloudscape error policy
1281:             */
1282:            public void dropStreamContainer(long segmentId, long containerId)
1283:                    throws StandardException {
1284:
1285:                setActiveState();
1286:
1287:                dataFactory.dropStreamContainer(this , segmentId, containerId);
1288:            }
1289:
1290:            /**
1291:            	Recreate a container during redo recovery.
1292:
1293:                Used only during redo recovery while processing log records which
1294:                are trying to create a container, and no valid container is found
1295:                in the database.
1296:
1297:            	@exception StandardException  Standard cloudscape exception policy
1298:            	@see RawTransaction#reCreateContainerForRedoRecovery
1299:             */
1300:            public void reCreateContainerForRedoRecovery(long segmentId,
1301:                    long containerId, ByteArray containerInfo)
1302:                    throws StandardException {
1303:                setActiveState();
1304:
1305:                dataFactory.reCreateContainerForRedoRecovery(this , segmentId,
1306:                        containerId, containerInfo);
1307:            }
1308:
1309:            /**
1310:            	@see Transaction#dropContainer
1311:            	@exception StandardException Standard Cloudscape error policy
1312:             */
1313:            public void dropContainer(ContainerKey containerId)
1314:                    throws StandardException {
1315:
1316:                setActiveState();
1317:
1318:                dataFactory.dropContainer(this , containerId);
1319:            }
1320:
1321:            /**
1322:                @exception StandardException  Standard cloudscape exception policy
1323:            	@see Transaction#setSavePoint
1324:             */
1325:            public int setSavePoint(String name, Object kindOfSavepoint)
1326:                    throws StandardException {
1327:
1328:                if (kindOfSavepoint != null
1329:                        && kindOfSavepoint instanceof  String) {
1330:                    //that means we are trying to set a SQL savepoint
1331:
1332:                    //error if this SQL savepoint is getting nested into other user 
1333:                    // defined savepoints
1334:                    throwExceptionIfSQLSavepointNotAllowed(kindOfSavepoint);
1335:                }
1336:
1337:                // while setting a savepoint, we just want to see if there is a 
1338:                // savepoint with the passed name already in the system.
1339:                if (getSavePointPosition(name, kindOfSavepoint, false) != -1) {
1340:                    throw StandardException
1341:                            .newException(SQLState.XACT_SAVEPOINT_EXISTS);
1342:                }
1343:
1344:                if (savePoints == null)
1345:                    savePoints = new Stack();
1346:
1347:                savePoints.push(new SavePoint(name, kindOfSavepoint));
1348:
1349:                if (SanityManager.DEBUG) {
1350:
1351:                    if (SanityManager.DEBUG_ON("memoryLeakTrace")) {
1352:
1353:                        if (savePoints.size() > 20)
1354:                            System.out
1355:                                    .println("memoryLeakTrace:Xact:savepoints "
1356:                                            + savePoints.size());
1357:                    }
1358:                }
1359:                return savePoints.size();
1360:            }
1361:
1362:            // SQL savepoint can't be nested inside other user defined savepoints. To 
1363:            // enforce this, we check if there are already user savepoint(SQL/JDBC)
1364:            // defined in the transaction. If yes, then throw an exception
1365:
1366:            /**
1367:                @exception StandardException  Standard cloudscape exception policy
1368:            	@see Transaction#setSavePoint
1369:             */
1370:            private void throwExceptionIfSQLSavepointNotAllowed(
1371:                    Object kindOfSavepoint) throws StandardException {
1372:
1373:                boolean foundUserSavepoint = false;
1374:
1375:                if ((savePoints != null) && !savePoints.empty()) {
1376:                    for (int i = savePoints.size() - 1; i >= 0; i--) {
1377:                        SavePoint sp = (SavePoint) savePoints.elementAt(i);
1378:                        if (sp.isThisUserDefinedsavepoint()) {
1379:                            //found a user defined savepoint
1380:
1381:                            foundUserSavepoint = true;
1382:                            break;
1383:                        }
1384:                    }
1385:                }
1386:
1387:                if (foundUserSavepoint)
1388:                    throw StandardException
1389:                            .newException(SQLState.XACT_MAX_SAVEPOINT_LEVEL_REACHED);
1390:            }
1391:
1392:            /**
1393:                @exception StandardException  Standard cloudscape exception policy
1394:            	@see Transaction#releaseSavePoint
1395:             */
1396:            public int releaseSavePoint(String name, Object kindOfSavepoint)
1397:                    throws StandardException {
1398:                int position = getSavePointPosition(name, kindOfSavepoint, true);
1399:
1400:                if (position == -1) {
1401:                    // following means this is a JDBC savepoint. 
1402:                    // We prepend i./e. to JDBC savepoint names in JDBC layer.
1403:                    // Need to trim that here before giving error
1404:
1405:                    if (kindOfSavepoint != null
1406:                            && !(kindOfSavepoint instanceof  String)) {
1407:                        // this means this is a JDBC savepoint. 
1408:                        // We append "i."/"e." to JDBC savepoint names. 
1409:                        // Trimming that here before giving error
1410:
1411:                        name = name.substring(2);
1412:                    }
1413:                    throw StandardException.newException(
1414:                            SQLState.XACT_SAVEPOINT_NOT_FOUND, name);
1415:                }
1416:
1417:                popSavePoints(position, true);
1418:                return savePoints.size();
1419:            }
1420:
1421:            /** 
1422:                @exception StandardException  Standard cloudscape exception policy
1423:            	@see Transaction#rollbackToSavePoint
1424:             */
1425:            public int rollbackToSavePoint(String name, Object kindOfSavepoint)
1426:                    throws StandardException {
1427:                int position = getSavePointPosition(name, kindOfSavepoint, true);
1428:
1429:                if (position == -1) {
1430:                    // following means this is a JDBC savepoint. 
1431:                    // We append i./e. to JDBC savepoint names in JDBC layer.
1432:                    // Need to trim that here before giving error
1433:                    if (kindOfSavepoint != null
1434:                            && !(kindOfSavepoint instanceof  String))
1435:                        name = name.substring(2);
1436:                    throw StandardException.newException(
1437:                            SQLState.XACT_SAVEPOINT_NOT_FOUND, name);
1438:                }
1439:
1440:                notifyObservers(SAVEPOINT_ROLLBACK);
1441:
1442:                popSavePoints(position, false);
1443:                return savePoints.size();
1444:            }
1445:
1446:            /*
1447:             **	Implementation specific methods
1448:             */
1449:
1450:            /**
1451:            	Get the Logger object used to write log records to the transaction log.
1452:             */
1453:            private void getLogger() {
1454:
1455:                logger = logFactory.getLogger();
1456:            }
1457:
1458:            /**
1459:            	Transform this identity to the one stored in transaction table entry.
1460:            	Used by recovery only!
1461:             */
1462:            protected void assumeIdentity(TransactionTableEntry ent) {
1463:                if (ent != null) {
1464:                    if (SanityManager.DEBUG) {
1465:                        SanityManager.ASSERT(ent.getXid() != null,
1466:                                "TTE.xid is null");
1467:
1468:                        SanityManager.ASSERT(ent.getFirstLog() != null,
1469:                                "TTE.firstLog is null");
1470:                    }
1471:
1472:                    // I am the transaction that is using this TransactionTableEntry
1473:                    ent.setXact(this );
1474:
1475:                    myId = ent.getXid();
1476:                    logStart = ent.getFirstLog();
1477:                    logLast = ent.getLastLog();
1478:
1479:                    // This routine is only used by recovery to assume the identity
1480:                    // of the transaction for each log record during redo and undo.
1481:                    // For this purpose the transaction should act like a local 
1482:                    // transaction, and ignore the fact that it may or may not be
1483:                    // an XA global transaction - this is necessary as global 
1484:                    // transactions can only be committed or aborted once, but 
1485:                    // recovery needs to reuse the same xact over and over again.  
1486:                    // For this purpose set myGlobalId to null so it is treated as
1487:                    // a local xact - the entry in the transaction table will 
1488:                    // track that in reality it is a global id and remember it's
1489:                    // value.
1490:                    myGlobalId = null;
1491:
1492:                    // I am very active
1493:                    if (state == IDLE)
1494:                        state = ACTIVE;
1495:
1496:                    if (SanityManager.DEBUG) {
1497:                        if (state != ACTIVE && state != UPDATE
1498:                                && state != PREPARED)
1499:                            SanityManager
1500:                                    .THROWASSERT("recovery transaction have illegal state "
1501:                                            + state + "xact = " + this );
1502:                    }
1503:
1504:                    if (logger == null)
1505:                        getLogger();
1506:
1507:                    savedEndStatus = 0;
1508:                } else {
1509:                    myGlobalId = null;
1510:                    myId = null;
1511:                    logStart = null;
1512:                    logLast = null;
1513:                    state = IDLE;
1514:                }
1515:            }
1516:
1517:            /**
1518:             * Assume complete identity of the given Transaction Table Entry.
1519:             * <p>
1520:             * Used by the final phase of the recovery to create new real transactions
1521:             * to take on the identity of in-doubt prepared transactions found during
1522:             * redo.  Need to assume the globalId.
1523:             *
1524:             * @param ent The original entry we are assuming the identity of.
1525:             *
1526:             **/
1527:            protected void assumeGlobalXactIdentity(TransactionTableEntry ent) {
1528:                if (SanityManager.DEBUG) {
1529:                    SanityManager.ASSERT(ent != null);
1530:                    SanityManager.ASSERT(ent.getXid() != null,
1531:                            "TTE.xid is null");
1532:                    SanityManager.ASSERT(ent.getFirstLog() != null,
1533:                            "TTE.firstLog is null");
1534:                    SanityManager.ASSERT(ent.isPrepared());
1535:                }
1536:
1537:                myId = ent.getXid();
1538:                myGlobalId = ent.getGid();
1539:                logStart = ent.getFirstLog();
1540:                logLast = ent.getLastLog();
1541:
1542:                // I am very active
1543:                if (state == IDLE) {
1544:                    if (SanityManager.DEBUG) {
1545:                        if (SanityManager.DEBUG_ON("XATrace"))
1546:                            SanityManager
1547:                                    .DEBUG("XATrace",
1548:                                            "set active state in assume Global XactIdentity");
1549:                    }
1550:
1551:                    state = ACTIVE;
1552:                }
1553:
1554:                if (ent.isPrepared())
1555:                    state = PREPARED;
1556:
1557:                // I am the transaction that is using this TransactionTableEntry
1558:                ent.setXact(this );
1559:
1560:                if (SanityManager.DEBUG) {
1561:                    if (state != ACTIVE && state != UPDATE && state != PREPARED)
1562:                        SanityManager
1563:                                .THROWASSERT("recovery transaction have illegal state "
1564:                                        + state + "xact = " + this );
1565:                }
1566:
1567:                if (logger == null)
1568:                    getLogger();
1569:
1570:                savedEndStatus = 0;
1571:
1572:                if (SanityManager.DEBUG) {
1573:                    SanityManager.ASSERT(myGlobalId != null);
1574:
1575:                    // at least right now only prepared xact call this during recovery.
1576:                    SanityManager.ASSERT(state == PREPARED);
1577:                }
1578:            }
1579:
1580:            /**
1581:            	Move the transaction into the update state.
1582:            	@exception StandardException problem setting a transaction id
1583:             */
1584:            private final void setUpdateState() throws StandardException {
1585:
1586:                /*
1587:                System.out.println("calling setUpdateState() - readOnly = " + readOnly +
1588:                        ";this = " + this);
1589:                System.out.println("calling setUpdateState():");
1590:                        (new Throwable()).printStackTrace();
1591:                 */
1592:
1593:                if (SanityManager.DEBUG) {
1594:                    SanityManager
1595:                            .ASSERT(state == ACTIVE,
1596:                                    "setting update state without first going thru ACTIVE state");
1597:
1598:                    SanityManager
1599:                            .ASSERT(myId != null,
1600:                                    "setting update state to a trasnaction with Null ID");
1601:                }
1602:
1603:                if (SanityManager.DEBUG) {
1604:                    if (SanityManager.DEBUG_ON("XATrace")) {
1605:                        SanityManager.DEBUG("XATrace", "set update state");
1606:                        SanityManager.showTrace(new Throwable());
1607:                    }
1608:                }
1609:
1610:                if (readOnly) {
1611:                    throw StandardException
1612:                            .newException(SQLState.XACT_PROTOCOL_VIOLATION);
1613:                }
1614:
1615:                state = UPDATE;
1616:            }
1617:
1618:            protected void setIdleState() {
1619:
1620:                if (SanityManager.DEBUG)
1621:                    SanityManager.ASSERT(myId != null,
1622:                            "setIdleState got null ID");
1623:
1624:                if (SanityManager.DEBUG) {
1625:                    if (SanityManager.DEBUG_ON("TranTrace")) {
1626:                        SanityManager.DEBUG("TranTrace",
1627:                                "transaction going idle " + myId);
1628:
1629:                        SanityManager.showTrace(new Throwable("TranTrace"));
1630:                    }
1631:                }
1632:
1633:                /* MT - single thread throught synchronizing this.  Even though no other
1634:                 * thread can call this, they may call isActive which needs to be
1635:                 * synchronized with state transaction into or out of the idle state
1636:                 */
1637:                // synchronized(this) -- int access, implicit synchronization
1638:                // due to atomic action
1639:                {
1640:                    state = IDLE;
1641:                }
1642:
1643:                seenUpdates = false;
1644:
1645:                // these fields will NOT be accessed by the checkpoint thread at the
1646:                // same time because the doMe method of EndXact removed this
1647:                // transaction from the "update transaction" list, therefore when the
1648:                // checkpoint writes out the transaction table, this transaction will
1649:                // be skipped.  OK to just change it without synchronization here.
1650:
1651:                logStart = null;
1652:                logLast = null;
1653:
1654:                if (SanityManager.DEBUG) {
1655:                    if (SanityManager.DEBUG_ON("XATrace"))
1656:                        SanityManager.DEBUG("XATrace", "set idle state : "
1657:                                + state + " " + this );
1658:                }
1659:
1660:            }
1661:
1662:            protected final void setActiveState() throws StandardException {
1663:
1664:                if ((state == CLOSED) || (!inAbort() && (state == PREPARED))) {
1665:                    // This is where we catch attempted activity on a prepared xact.
1666:                    throw StandardException
1667:                            .newException(SQLState.XACT_PROTOCOL_VIOLATION);
1668:                }
1669:
1670:                if (SanityManager.DEBUG)
1671:                    SanityManager.ASSERT(myId != null,
1672:                            "setActiveState got null ID");
1673:
1674:                if (state == IDLE) {
1675:                    synchronized (this ) {
1676:                        state = ACTIVE;
1677:                    }
1678:
1679:                    if (SanityManager.DEBUG) {
1680:                        if (SanityManager.DEBUG_ON("XATrace")) {
1681:                            SanityManager.DEBUG("XATrace", "set active state "
1682:                                    + this );
1683:                            SanityManager.showTrace(new Throwable("XATrace"));
1684:                        }
1685:                    }
1686:
1687:                    if (!justCreated)
1688:                        xactFactory.setNewTransactionId(myId, this );
1689:
1690:                    justCreated = false;
1691:
1692:                    if (SanityManager.DEBUG) {
1693:                        if (SanityManager.DEBUG_ON("TranTrace")) {
1694:                            SanityManager.DEBUG("TranTrace",
1695:                                    "transaction going active " + myId);
1696:
1697:                            SanityManager.showTrace(new Throwable("TranTrace"));
1698:                        }
1699:                    }
1700:
1701:                }
1702:            }
1703:
1704:            /**
1705:             * Move the state of the transaction from UPDATE to PREPARE.
1706:             * <p>
1707:             * The state transition should only be from UPDATE to PREPARE.  Read-only
1708:             * transactions (IDLE and ACTIVE) will never be prepared, they will be
1709:             * commited when the prepare is requested.  Only Update transactions will
1710:             * be allowed to go to prepared state.
1711:             * <p>
1712:             *
1713:             * @exception  StandardException  Standard exception policy.
1714:             **/
1715:            protected final void setPrepareState() throws StandardException {
1716:                if (state == PREPARED || state == CLOSED) {
1717:                    throw StandardException
1718:                            .newException(SQLState.XACT_PROTOCOL_VIOLATION);
1719:                }
1720:
1721:                if (SanityManager.DEBUG) {
1722:                    SanityManager
1723:                            .ASSERT(state == UPDATE,
1724:                                    "setting PREPARED state without first going thru UPDATE state");
1725:                    SanityManager
1726:                            .ASSERT(myId != null,
1727:                                    "setting PREPARED state to a transaction with Null ID");
1728:                }
1729:
1730:                state = PREPARED;
1731:            }
1732:
1733:            public final LockingPolicy defaultLockingPolicy() {
1734:                return defaultLocking;
1735:            }
1736:
1737:            private final void releaseAllLocks() {
1738:
1739:                getLockFactory().unlockGroup(getCompatibilitySpace(), this );
1740:            }
1741:
1742:            void resetDefaultLocking() {
1743:
1744:                setDefaultLockingPolicy(newLockingPolicy(
1745:                        LockingPolicy.MODE_RECORD,
1746:                        TransactionController.ISOLATION_SERIALIZABLE, true));
1747:
1748:                if (SanityManager.DEBUG) {
1749:                    SanityManager.ASSERT(defaultLocking != null);
1750:                }
1751:
1752:            }
1753:
1754:            protected void preComplete(Integer commitOrAbort)
1755:                    throws StandardException {
1756:
1757:                /* If a transaction is in COMMIT/ABORT at this point, most probably
1758:                 * some thing went wrong in earlier attempt to commit or abort,
1759:                 * so we don't know wther the log records got written in previous
1760:                 * attempt. It's is better to bring down the system than make recovery
1761:                 * fail with a duplicate log records of COMMIT/ABORT for the same Transaction.
1762:                 */
1763:                if (inComplete != null)
1764:                    if (commitOrAbort.equals(COMMIT))
1765:                        throw logFactory.markCorrupt(StandardException
1766:                                .newException(SQLState.XACT_COMMIT_EXCEPTION));
1767:                    else
1768:                        throw logFactory.markCorrupt(StandardException
1769:                                .newException(SQLState.XACT_ABORT_EXCEPTION));
1770:
1771:                inComplete = commitOrAbort;
1772:                if (!postCompleteMode)
1773:                    doComplete(commitOrAbort);
1774:
1775:            }
1776:
1777:            protected void postComplete(int commitflag, Integer commitOrAbort)
1778:                    throws StandardException {
1779:
1780:                if (postCompleteMode)
1781:                    doComplete(commitOrAbort);
1782:
1783:                // if we are want to commitNoSync with KEEP_LOCKS flag set, don't
1784:                // release any locks
1785:                if ((commitflag & Transaction.KEEP_LOCKS) == 0) {
1786:                    releaseAllLocks();
1787:                } else {
1788:                    if (SanityManager.DEBUG) {
1789:                        SanityManager.ASSERT(commitOrAbort.equals(COMMIT),
1790:                                "cannot keep locks around after an ABORT");
1791:                    }
1792:                }
1793:
1794:                setIdleState();
1795:
1796:                inComplete = null;
1797:            }
1798:
1799:            protected void doComplete(Integer commitOrAbort)
1800:                    throws StandardException {
1801:
1802:                // throw away all our savepoints
1803:                if (savePoints != null)
1804:                    savePoints.removeAllElements();
1805:
1806:                // notify any of our observers that we are completing.
1807:                notifyObservers(commitOrAbort);
1808:
1809:                checkObserverException();
1810:
1811:                if (SanityManager.DEBUG) {
1812:                    if (countObservers() != 0) {
1813:                        System.out
1814:                                .println("There should be 0 observers, but we still have "
1815:                                        + countObservers() + " observers.");
1816:                        notifyObservers(null);
1817:                    }
1818:                }
1819:            }
1820:
1821:            private void checkObserverException() throws StandardException {
1822:                if (observerException != null) {
1823:                    StandardException se = observerException;
1824:                    observerException = null;
1825:                    throw se;
1826:                }
1827:            }
1828:
1829:            /**
1830:              If this is a user transaction (not an internal or nested top
1831:              transaction), and this is not already taking care of post
1832:              commit work, and not an XA transaction, then take care of hi prioirty 
1833:              work right now using this thread and this context manager.  
1834:              Otherwise, leave it to the post commit daemon.
1835:             */
1836:            protected boolean doPostCommitWorkInTran() {
1837:                return (!inPostCommitProcessing && !recoveryTransaction
1838:                        && isUserTransaction() && (myGlobalId == null));
1839:            }
1840:
1841:            public boolean handlesPostTerminationWork() {
1842:                // recovery transaction cannot handle post termination work
1843:                return (recoveryTransaction == false);
1844:            }
1845:
1846:            public void recoveryTransaction() {
1847:                recoveryTransaction = true;
1848:
1849:                // remove myself from the transaction table because I am really a
1850:                // "fake" transaction.  All interaction I have with the transaction
1851:                // table should happen after I have assumed the identity of one of the
1852:                // recovery transaction that has its state frozen in the transaction
1853:                // table. 
1854:                xactFactory.remove(myId);
1855:
1856:            }
1857:
1858:            private final void postTermination() throws StandardException {
1859:                // move all the postTermination work to the postCommit queue
1860:                int count = (postTerminationWorks == null) ? 0
1861:                        : postTerminationWorks.size();
1862:
1863:                for (int i = 0; i < count; i++)
1864:                    addPostCommitWork((Serviceable) postTerminationWorks.get(i));
1865:
1866:                if (count > 0)
1867:                    postTerminationWorks.clear();
1868:
1869:                // if there are post commit work to be done, transfer them to the
1870:                // daemon.  The log is flushed, all locks released and the
1871:                // transaction has ended at this point.
1872:                if (postCommitWorks != null && !postCommitWorks.isEmpty()) {
1873:                    int pcsize = postCommitWorks.size();
1874:
1875:                    // do we want to do post commit work with this transaction object?
1876:                    if (doPostCommitWorkInTran()) {
1877:                        try {
1878:                            inPostCommitProcessing = true;
1879:
1880:                            // to avoid confusion, copy the post commit work to an array if this
1881:                            // is going to do some work now
1882:                            Serviceable[] work = new Serviceable[pcsize];
1883:                            work = (Serviceable[]) postCommitWorks
1884:                                    .toArray(work);
1885:
1886:                            // clear this for post commit processing to queue its own post
1887:                            // commit works - when it commits, it will send all its post
1888:                            // commit request to the daemon instead of dealing with it here.
1889:                            postCommitWorks.clear();
1890:
1891:                            //All the post commit work that is part  of the database creation
1892:                            //should be done on this thread immediately.
1893:                            boolean doWorkInThisThread = xactFactory
1894:                                    .inDatabaseCreation();
1895:
1896:                            for (int i = 0; i < pcsize; i++) {
1897:
1898:                                //process work that should be done immediately or
1899:                                //when we  are in still in database creattion.
1900:                                //All the other work should be submitted 
1901:                                //to the post commit thread to be processed asynchronously
1902:                                if (doWorkInThisThread
1903:                                        || work[i].serviceImmediately()) {
1904:                                    try {
1905:                                        // this may cause other post commit work to be
1906:                                        // added.  when that transaction commits, those
1907:                                        // work will be transfered to the daemon
1908:                                        if (work[i].performWork(xc
1909:                                                .getContextManager()) == Serviceable.DONE)
1910:                                            work[i] = null;
1911:
1912:                                        // if REQUEUE, leave it on for the postcommit
1913:                                        // daemon to handle
1914:                                    } catch (StandardException se) {
1915:                                        // don't try to service this again
1916:                                        work[i] = null;
1917:
1918:                                        // try to handle it here.  If we fail, then let the error percolate.
1919:                                        xc.cleanupOnError(se);
1920:                                    }
1921:                                }
1922:
1923:                                // either it need not be serviedASAP or it needs
1924:                                // requeueing, send it off.   Note that this is one case
1925:                                // where a REQUEUE ends up in the high priority queue.
1926:                                // Unfortunately, there is no easy way to tell.  If the
1927:                                // Servicable is well mannered, it can change itself from
1928:                                // serviceASAP to not serviceASAP if it returns REQUEUE.
1929:                                if (work[i] != null) {
1930:                                    boolean needHelp = xactFactory
1931:                                            .submitPostCommitWork(work[i]);
1932:                                    work[i] = null;
1933:                                    if (needHelp)
1934:                                        doWorkInThisThread = true;
1935:                                }
1936:                            }
1937:                        } finally {
1938:                            inPostCommitProcessing = false;
1939:
1940:                            // if something untoward happends, clear the queue.
1941:                            if (postCommitWorks != null)
1942:                                postCommitWorks.clear();
1943:                        }
1944:
1945:                    } else {
1946:                        // this is for non-user transaction or post commit work that is
1947:                        // submitted in PostCommitProcessing.  (i.e., a post commit
1948:                        // work submitting other post commit work)
1949:                        for (int i = 0; i < pcsize; i++) {
1950:                            // SanityManager.DEBUG_PRINT("PostTermination",postCommitWorks.elementAt((i)).toString());
1951:                            xactFactory
1952:                                    .submitPostCommitWork((Serviceable) postCommitWorks
1953:                                            .get((i)));
1954:                        }
1955:                    }
1956:
1957:                    postCommitWorks.clear();
1958:
1959:                }
1960:
1961:                // any backup blocking operations (like unlogged ops) in this 
1962:                // transaction are done with post commit/abort work that needs be
1963:                // done in the same trasaction,  unblock the backup.
1964:                unblockBackup();
1965:            }
1966:
1967:            /**
1968:            	Does a save point exist in the stack with the given name.
1969:            	Returns the position of the savepoint in the array
1970:             */
1971:            private int getSavePointPosition(String name,
1972:                    Object kindOfSavepoint, boolean forRollbackOrRelease) {
1973:                if ((savePoints == null) || (savePoints.empty()))
1974:                    return -1;
1975:
1976:                for (int i = savePoints.size() - 1; i >= 0; i--) {
1977:                    SavePoint savepoint = (SavePoint) savePoints.elementAt(i);
1978:
1979:                    if (savepoint.getName().equals(name)) {
1980:                        if (forRollbackOrRelease
1981:                                && savepoint.getKindOfSavepoint() != null) {
1982:                            if (savepoint.getKindOfSavepoint().equals(
1983:                                    kindOfSavepoint))
1984:                                return (i);
1985:                        } else {
1986:                            return (i);
1987:                        }
1988:                    }
1989:                }
1990:                return -1;
1991:            }
1992:
1993:            /**
1994:            	Pop all savepoints upto the one with the given name and rollback
1995:            	all changes made since this savepoint was pushed.
1996:            	If release is true then this savepoint is popped as well,
1997:            	otherwise it is left in the stack (at the top).
1998:
1999:            	@return true if any work is rolled back, false if no work is rolled back
2000:            	@exception StandardException	Standard cloudscape policy
2001:            	@exception StandardException Thrown if a error of severity less than TransactionException#SEVERITY
2002:            	is encountered during the rollback of this savepoint.
2003:             */
2004:            protected boolean popSavePoints(int position, boolean release)
2005:                    throws StandardException {
2006:
2007:                if (release) {
2008:                    savePoints.setSize(position);
2009:                    return false;
2010:                }
2011:
2012:                LogInstant rollbackTo = null;
2013:
2014:                int size = savePoints.size();
2015:                for (int i = position; i < size; i++) {
2016:                    SavePoint rollbackSavePoint = (SavePoint) savePoints
2017:                            .elementAt(i);
2018:
2019:                    LogInstant li = rollbackSavePoint.getSavePoint();
2020:                    if (li != null) {
2021:                        rollbackTo = li;
2022:                        break;
2023:                    }
2024:                }
2025:
2026:                savePoints.setSize(position + 1);
2027:
2028:                if (rollbackTo == null)
2029:                    return false;
2030:
2031:                // now perform the rollback
2032:                try {
2033:
2034:                    logger.undo(this , getId(), rollbackTo, getLastLogInstant());
2035:
2036:                } catch (StandardException se) {
2037:
2038:                    // This catches any exceptions that have Transaction severity
2039:                    // or less (e.g. Statement exception). If we received any lesser
2040:                    // error then we abort the transaction anyway.
2041:
2042:                    if (se.getSeverity() < ExceptionSeverity.TRANSACTION_SEVERITY) {
2043:                        throw StandardException.newException(
2044:                                SQLState.XACT_ROLLBACK_EXCEPTION, se);
2045:                    }
2046:
2047:                    throw se;
2048:                }
2049:
2050:                return true;
2051:            }
2052:
2053:            /**
2054:            	@exception StandardException Cloudscape Standard error policy
2055:             */
2056:            public RawTransaction startNestedTopTransaction()
2057:                    throws StandardException {
2058:
2059:                return xactFactory.startNestedTopTransaction(xc.getFactory(),
2060:                        xc.getContextManager());
2061:            }
2062:
2063:            /**
2064:             * see if this transaction is a user transaction.
2065:             *
2066:             * @return true if this transaction is a user transaction
2067:             */
2068:            private boolean isUserTransaction() {
2069:                String context_id = getContextId();
2070:
2071:                return ((context_id == XactFactory.USER_CONTEXT_ID || context_id
2072:                        .equals(XactFactory.USER_CONTEXT_ID)));
2073:            }
2074:
2075:            /**
2076:             * see if this transaction has ever done anything.
2077:             *
2078:             * MT - single thread through synchronizing this.  This method may be
2079:             * called by other thread to test the state of this transaction.  That's
2080:             * why we need to synchronize with all methods which enters or exits the
2081:             * Idle state.
2082:             *
2083:             * Local method which read the state need not be synchronized because 
2084:             * the other thread may look at the state but it may not change it.
2085:             *
2086:             * @return true if this transaction is not in idle or closed state
2087:             */
2088:            public final boolean isActive() {
2089:                // synchronized(this) -- int access, implicit synchronization
2090:                // due to atomic action
2091:                int localState = state;
2092:
2093:                return (localState != CLOSED && localState != IDLE);
2094:            }
2095:
2096:            /**
2097:             * see if this transaction is in PREPARED state.
2098:             *
2099:             * MT - single thread through synchronizing this.  This method may be
2100:             * called by other thread to test the state of this transaction.
2101:             *
2102:             * @return true if this transaction is in PREPARED state.
2103:             */
2104:            public final boolean isPrepared() {
2105:                // synchronized(this) -- int access, implicit synchronization
2106:                // due to atomic action
2107:                return (state == PREPARED);
2108:            }
2109:
2110:            /**
2111:            	See if this transaction is in the idle state, called by other thread to
2112:            	test the state of this transaction.  That's why we need to synchronzied
2113:            	with all methods whcih enters or exits the idle state
2114:
2115:            	@return true if it is idle, otherwise false
2116:             */
2117:            public boolean isIdle() {
2118:                // synchronized(this) -- int access, implicit synchronization
2119:                // due to atomic action
2120:                if (SanityManager.DEBUG) {
2121:                    if (SanityManager.DEBUG_ON("XATrace"))
2122:                        SanityManager.DEBUG("XATrace",
2123:                                "RawTran, isIdle, state = " + state);
2124:                }
2125:
2126:                return (state == IDLE);
2127:            }
2128:
2129:            /**
2130:            	see if this transaction is in a pristine state.
2131:
2132:            	<BR>MT - called only by the same thread that owns the xact, no need to synchronize.
2133:
2134:            	@return true if it hasn't done any updates, otherwise false
2135:             */
2136:            public boolean isPristine() {
2137:                return (state == IDLE || state == ACTIVE);
2138:            }
2139:
2140:            public boolean inAbort() {
2141:                return ABORT.equals(inComplete);
2142:            }
2143:
2144:            public FileResource getFileHandler() {
2145:                return dataFactory.getFileHandler();
2146:            }
2147:
2148:            /**
2149:             * put this into the beginXact log record to help recovery
2150:             * if we needs to rolled back first, put that in
2151:             */
2152:            protected int statusForBeginXactLog() {
2153:                return recoveryRollbackFirst() ? RECOVERY_ROLLBACK_FIRST : 0;
2154:            }
2155:
2156:            /**
2157:             * put this into the endXact log record to help recovery, 
2158:             * nothing to add
2159:             */
2160:            protected int statusForEndXactLog() {
2161:                // during recovery, the beginXact may be logged by a non-standard
2162:                // transaction and hence the end xact it log
2163:                // must also contain whatever a non-standard Transaction will output.  
2164:                return savedEndStatus;
2165:            }
2166:
2167:            /**	
2168:            	Set the transaction to issue pre complete work at postComplete
2169:            	time, instead of preComplete time. This means that latches
2170:            	and containers will be held open until after a commit or an abort.
2171:             */
2172:            void setPostComplete() {
2173:                postCompleteMode = true;
2174:            }
2175:
2176:            /*
2177:             * Make the transaction block the online backup.
2178:             *
2179:             * @param wait if <tt>true</tt>, waits until the transaction
2180:             *             can block the backup.
2181:             * @return     <tt>true</tt> if the transaction  blocked the  
2182:             *             backup.  <tt>false</tt> otherwise.
2183:             * @exception StandardException if interrupted while waiting 
2184:             *            for the backup in progress to complete.
2185:             */
2186:            public boolean blockBackup(boolean wait) throws StandardException {
2187:                if (!backupBlocked) {
2188:                    backupBlocked = xactFactory.blockBackup(wait);
2189:                }
2190:
2191:                return backupBlocked;
2192:            }
2193:
2194:            /*
2195:             * Unblock the backup, if it was blocked by some operation in 
2196:             * this transaction. Unblocking is done at commit/abort of this 
2197:             * transaction.
2198:             */
2199:            private void unblockBackup() {
2200:                if (backupBlocked)
2201:                    xactFactory.unblockBackup();
2202:                backupBlocked = false;
2203:            }
2204:
2205:            /**
2206:             * Check if the transaction is blocking the backup ?
2207:             * @return <tt> true </tt> if this transaction is 
2208:             *         blocking the backup, otherwise <tt> false </tt>
2209:             */
2210:            public boolean isBlockingBackup() {
2211:                return backupBlocked;
2212:            }
2213:
2214:            /*
2215:             ** Lock escalation related
2216:             */
2217:
2218:            /*
2219:             ** Methods of Limit
2220:             */
2221:
2222:            public void reached(Object compatabilitySpace, Object group,
2223:                    int limit, Enumeration lockList, int lockCount)
2224:                    throws StandardException {
2225:
2226:                // Count row locks by table
2227:                Dictionary containers = new java.util.Hashtable();
2228:
2229:                for (; lockList.hasMoreElements();) {
2230:
2231:                    Object plainLock = lockList.nextElement();
2232:                    if (!(plainLock instanceof  RecordHandle)) {
2233:                        // only interested in rows locks
2234:                        continue;
2235:                    }
2236:
2237:                    ContainerKey ckey = ((RecordHandle) plainLock)
2238:                            .getContainerId();
2239:
2240:                    LockCount lc = (LockCount) containers.get(ckey);
2241:                    if (lc == null) {
2242:                        lc = new LockCount();
2243:                        containers.put(ckey, lc);
2244:                    }
2245:                    lc.count++;
2246:                }
2247:
2248:                // Determine the threshold for lock escalation
2249:                // based upon our own limit, not the current count
2250:                int threshold = limit / (containers.size() + 1);
2251:                if (threshold < (limit / 4))
2252:                    threshold = limit / 4;
2253:
2254:                // try to table lock all tables that are above
2255:                // this threshold
2256:
2257:                boolean didEscalate = false;
2258:                for (Enumeration e = containers.keys(); e.hasMoreElements();) {
2259:                    ContainerKey ckey = (ContainerKey) e.nextElement();
2260:
2261:                    LockCount lc = (LockCount) containers.get(ckey);
2262:
2263:                    if (lc.count < threshold) {
2264:                        continue;
2265:                    }
2266:
2267:                    try {
2268:                        if (openContainer(ckey, new RowLocking3Escalate(
2269:                                getLockFactory()),
2270:                                ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY
2271:                                        | ContainerHandle.MODE_FORUPDATE
2272:                                        | ContainerHandle.MODE_LOCK_NOWAIT) != null) {
2273:
2274:                            didEscalate = true;
2275:                        }
2276:                    } catch (StandardException se) {
2277:                        if (!se.getMessageId().equals(SQLState.LOCK_TIMEOUT)) {
2278:                            // if it is a timeout then escalate did not happen and
2279:                            // just fall through.
2280:                            throw se;
2281:                        }
2282:                    }
2283:                }
2284:
2285:                // Now notify all open containers that an escalation
2286:                // event happened. This will cause all open row locked
2287:                // containers to re-get their container intent locks,
2288:                // those that are now covered by a container lock due
2289:                // to the above escalation will move into no locking
2290:                // mode. The open containers that were not escalated
2291:                // will simply bump the lock count in the lock manager
2292:                // and will not have to wait for the lock they already have.
2293:                //
2294:                // It would be possible to pass in the notifyObservers
2295:                // some indication of which tables were escalated
2296:                // to reduce the extra lock call for the un-escalated
2297:                // containers. This would involve passing the Hashtable
2298:                // of escalated containers and having the update method
2299:                // of BaseContainerHandle look for its ContainerKey within it.
2300:                if (didEscalate) {
2301:                    notifyObservers(LOCK_ESCALATE);
2302:                    checkObserverException();
2303:                }
2304:            }
2305:
2306:            /**
2307:             * Convert a local transaction to a global transaction.
2308:             * <p>
2309:             * Must only be called a previous local transaction was created and exists
2310:             * in the context.  Can only be called if the current transaction is in
2311:             * the idle state, and no current global id.  
2312:             * <p>
2313:             * Simply call setTransactionId() which takes care of error checking.
2314:             *
2315:             * @param format_id the format id part of the Xid - ie. Xid.getFormatId().
2316:             * @param global_id the global transaction identifier part of XID - ie.
2317:             *                  Xid.getGlobalTransactionId().
2318:             * @param branch_id The branch qualifier of the Xid - ie. 
2319:             *                  Xid.getBranchQaulifier()
2320:             * 	
2321:             * @exception StandardException Standard exception policy.
2322:             **/
2323:            public void createXATransactionFromLocalTransaction(int format_id,
2324:                    byte[] global_id, byte[] branch_id)
2325:                    throws StandardException {
2326:                GlobalXactId gid = new GlobalXactId(format_id, global_id,
2327:                        branch_id);
2328:
2329:                if (((TransactionTable) xactFactory.getTransactionTable())
2330:                        .findTransactionContextByGlobalId(gid) != null) {
2331:                    throw StandardException
2332:                            .newException(SQLState.STORE_XA_XAER_DUPID);
2333:                }
2334:
2335:                setTransactionId(gid, this .getId());
2336:
2337:                if (SanityManager.DEBUG)
2338:                    SanityManager.ASSERT(myGlobalId != null);
2339:            }
2340:
2341:            /**
2342:             * This method is called to commit the current XA global transaction.
2343:             * <p>
2344:             * RESOLVE - how do we map to the "right" XAExceptions.
2345:             * <p>
2346:             *
2347:             * @param onePhase If true, the resource manager should use a one-phase
2348:             *                 commit protocol to commit the work done on behalf of 
2349:             *                 current xid.
2350:             *
2351:             * @exception  StandardException  Standard exception policy.
2352:             **/
2353:            public void xa_commit(boolean onePhase) throws StandardException {
2354:                if (SanityManager.DEBUG)
2355:                    SanityManager.ASSERT(state != CLOSED);
2356:
2357:                if (onePhase) {
2358:                    if (state == PREPARED) {
2359:                        throw StandardException
2360:                                .newException(SQLState.XACT_PROTOCOL_VIOLATION);
2361:                    }
2362:
2363:                    prepareCommit(COMMIT_SYNC);
2364:
2365:                    completeCommit(COMMIT_SYNC);
2366:                } else {
2367:                    if (state != PREPARED) {
2368:                        throw StandardException
2369:                                .newException(SQLState.XACT_PROTOCOL_VIOLATION);
2370:                    }
2371:
2372:                    prepareCommit(COMMIT_SYNC);
2373:
2374:                    completeCommit(COMMIT_SYNC);
2375:                }
2376:
2377:                return;
2378:            }
2379:
2380:            /**
2381:             * This method is called to ask the resource manager to prepare for
2382:             * a transaction commit of the transaction specified in xid.
2383:             * <p>
2384:             *
2385:             * @return         A value indicating the resource manager's vote on the
2386:             *                 the outcome of the transaction.  The possible values
2387:             *                 are:  XA_RDONLY or XA_OK.  If the resource manager wants
2388:             *                 to roll back the transaction, it should do so by 
2389:             *                 throwing an appropriate XAException in the prepare
2390:             *                 method.
2391:             *
2392:             * @exception  StandardException  Standard exception policy.
2393:             **/
2394:            public int xa_prepare() throws StandardException {
2395:                if (SanityManager.DEBUG) {
2396:                    if (state == CLOSED) {
2397:                        SanityManager.THROWASSERT("state = " + state
2398:                                + ";myGlobalId = " + myGlobalId);
2399:                    }
2400:
2401:                    if (SanityManager.DEBUG_ON("XATrace"))
2402:                        SanityManager.DEBUG("XATrace",
2403:                                "in xa_prepare, state is " + state);
2404:                }
2405:
2406:                if ((state == IDLE) || (state == ACTIVE)) {
2407:                    abort();
2408:                    return (Transaction.XA_RDONLY);
2409:                } else {
2410:                    prepareCommit(COMMIT_SYNC | COMMIT_PREPARE
2411:                            | Transaction.KEEP_LOCKS);
2412:                    //we set the following variable during prepareCommit 
2413:                    // to what we are doing, so we unset here.
2414:                    inComplete = null;
2415:
2416:                    setPrepareState();
2417:
2418:                    return (Transaction.XA_OK);
2419:                }
2420:            }
2421:
2422:            /**
2423:             * rollback the current global transaction.
2424:             * <p>
2425:             * The given transaction is roll'ed back and it's history is not
2426:             * maintained in the transaction table or long term log.
2427:             * <p>
2428:             *
2429:             * @exception  StandardException  Standard exception policy.
2430:             **/
2431:            public void xa_rollback() throws StandardException {
2432:                if (SanityManager.DEBUG)
2433:                    SanityManager.ASSERT(state != CLOSED);
2434:
2435:                abort();
2436:
2437:                return;
2438:            }
2439:
2440:            /**
2441:             * Return the xid as a string.
2442:             * <p>
2443:             * The virtual lock table depends on this routine returning just the
2444:             * local transaction id as a string, even if it is a global transaction.
2445:             * Joins between the lock table and the transaction table will not work
2446:             * if this routine returns anything other than myId.toString().
2447:             * <p>
2448:             *
2449:             * @return The xid as a string.
2450:             *
2451:             **/
2452:            public String toString() {
2453:                // needed for virtual lock table
2454:                try {
2455:                    return (myId.toString());
2456:                } catch (Throwable t) {
2457:                    // using try/catch rather than if (myId != null) because on
2458:                    // multiple processor sometimes myId was going null after the
2459:                    // test but before the use.
2460:                    return ("null");
2461:                }
2462:            }
2463:
2464:            /* 
2465:             * Get string id of the transaction that would be when the Transaction
2466:             * is IN active state.
2467:             *
2468:             *This transaction "name" will be the same id which is returned in
2469:             * the TransactionInfo information if Tx is already in Active State.
2470:             * If the Transaction is in IDLE state, Transaction ID is 
2471:             * incremented when getActiveStateTxIdString() on raw transaction is called,
2472:             * instead of the Tx ID being incremented when Transaction gets into
2473:             * active state. The reason for incrementing the Tx ID earlier than when Tx
2474:             * is actually goes into active state is some debug statement cases like 
2475:             * log statement text. SQL  statements are wriited  to log before they are
2476:             * actully executed; In such cases we would like to display the actual TX ID on which 
2477:             * locks are acquired when the statement is executed.
2478:             * @return The a string which identifies the transaction.  
2479:             */
2480:            public String getActiveStateTxIdString() {
2481:                if (!justCreated && state == IDLE) {
2482:                    // TransactionTable needs this
2483:                    xactFactory.setNewTransactionId(myId, this );
2484:                    //mark as if this tx is just created , so that setActiveState()
2485:                    //does not increment the transaction id number.
2486:                    justCreated = true;
2487:                }
2488:
2489:                return toString();
2490:            }
2491:
2492:            /* package */
2493:            String getState() {
2494:                int localState;
2495:
2496:                // synchronized(this) -- int assignment, implicit synchronization
2497:                // due to atomic action
2498:                {
2499:                    localState = state;
2500:                }
2501:
2502:                switch (localState) {
2503:                case CLOSED:
2504:                    return "CLOSED";
2505:                case IDLE:
2506:                    return "IDLE";
2507:                case ACTIVE:
2508:                case UPDATE:
2509:                    return "ACTIVE";
2510:
2511:                case PREPARED:
2512:                    return "PREPARED";
2513:                }
2514:                return null;
2515:            }
2516:
2517:            public String getTransName() {
2518:                return transName;
2519:            }
2520:
2521:            public void setTransName(String name) {
2522:                transName = name;
2523:            }
2524:
2525:            /**	
2526:            	Is the transaction in rollforward recovery
2527:             */
2528:            public boolean inRollForwardRecovery() {
2529:                return logFactory.inRFR();
2530:            }
2531:
2532:            /**	
2533:            	perform a  checkpoint during rollforward recovery
2534:             */
2535:            public void checkpointInRollForwardRecovery(LogInstant cinstant,
2536:                    long redoLWM) throws StandardException {
2537:                logFactory.checkpointInRFR(cinstant, redoLWM, dataFactory);
2538:            }
2539:
2540:        }
2541:
2542:        class LockCount {
2543:            int count;
2544:        }
ww_w__.___j_a_va__2s.___c__o__m__ | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.