All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.as400.access.JDTransactionManager Maven / Gradle / Ivy

There is a newer version: 20.0.8
Show newest version
///////////////////////////////////////////////////////////////////////////////
//                                                                             
// JTOpen (IBM Toolbox for Java - OSS version)                                 
//                                                                             
// Filename: JDTransactionManager.java
//                                                                             
// The source code contained herein is licensed under the IBM Public License   
// Version 1.0, which has been approved by the Open Source Initiative.         
// Copyright (C) 1997-2001 International Business Machines Corporation and     
// others. All rights reserved.                                                
//                                                                             
///////////////////////////////////////////////////////////////////////////////

package com.ibm.as400.access;

import java.sql.Connection;
import java.sql.SQLException;



/**

This class manages transaction operations.

In addition to issuing commits and rollbacks to the database, it manages auto-commit and the transaction isolation level. Auto-commit and the transaction isolation level interact in the following ways:

  • Auto-commit is on by default.
  • The transaction isolation level has no effect when auto- commit is on. (Auto-commit on is essentially the same thing as a transaction isolation level of Connection.TRANSACTION_NONE.) However, even when auto-commit is on, the current transaction isolation level is stored and returned upon request via getIsolation.
**/ // // Implementation notes: // // In the code and documentation, "transaction isolation level" // and "level" refer to the JDBC transaction isolation level (i.e. // Connection.TRANSACTION_* constants) and "commit mode" refers // to the value as set on the system. // // External to this class, only the transaction isolation level // is used. Internal to this class, the transaction isolation // level is mapped to the appropriate commit mode. Note that // not all transaction isolation levels are supported. // class JDTransactionManager { static final String copyright = "Copyright (C) 1997-2001 International Business Machines Corporation and others."; // @C6A Server commit mode constants // @C6A *CS and *CHG are different numbers on the system than in the client; these are the // @C6A numbers we need to send to the system in an AS400JDBCConnection.setServerAttributes(). private static final int COMMIT_SERVER_MODE_CS_ = 1; // TRANSACTION_READ_COMMITTED //@C6A private static final int COMMIT_SERVER_MODE_CHG_ = 2; // TRANSACTION_READ_UNCOMMITTED //@C6A // Client commit mode constants static final int COMMIT_MODE_NOT_SET_ = -1; private static final int COMMIT_MODE_NONE_ = 0; // TRANSACTION_NONE private static final int COMMIT_MODE_CHG_ = 1; // TRANSACTION_READ_UNCOMMITTED private static final int COMMIT_MODE_CS_ = 2; // TRANSACTION_READ_COMMITTED private static final int COMMIT_MODE_ALL_ = 3; // TRANSACTION_REPEATABLE_READ private static final int COMMIT_MODE_RR_ = 4; // TRANSACTION_SERIALIZABLE private static final String[] COMMIT_MODE_ = { "NONE", "CHG", "CS", "ALL", "RR"}; static final int CURSOR_HOLD_FALSE = 0; // @C1 @B1C static final int CURSOR_HOLD_TRUE = 1; // @C1 @B1C private boolean activeLocal_; // Is a local transaction active? @C4C private boolean activeGlobal_; // Is a global transaction active? @C4A private boolean autoCommit_; // Is auto-commit on? private AS400JDBCConnection connection_; private int holdIndicator_; // Current cursor hold indicator. @C1 private int currentCommitMode_; // Current commit mode. private int currentIsolationLevel_; // Current isolation level. private int id_; private int initialCommitMode_; // Initial commit mode. private boolean localAutoCommit_ = true; // @C4A private boolean localTransaction_ = true; // @C4A // @C5D private boolean newAutoCommitSupport_ = false; // @C5A private int serverCommitMode_; // Commit mode on the system. Always base off of JDBC transaction isolation level (currentCommitMode_) private int currentLocatorPersistence_=-1; /*@ABA*/ private int requestedLocatorPersistence_ = -1; /*@ABA*/ private boolean serverAllowsLocatorPersistenceChange_ = true; /** Constructor. The transaction isolation level should be initialized independently of this class. However, since commits and rollbacks always cause the database to revert back to the initial commit mode, we need to remember what this initial commit mode is, so we can predict how the system is behaving. @param connection Connection to the system. @param id The id. @param initialLevel One of the Connection.TRANSACTION_* values. @exception SQLException If an invalid or unsupported level is input. **/ JDTransactionManager (AS400JDBCConnection connection, int id, String initialLevel, boolean autoCommit) //@AC1 throws SQLException { activeLocal_ = false; // @C4C activeGlobal_ = false; // @C4A autoCommit_ = autoCommit; //@AC1 connection_ = connection; holdIndicator_ = CURSOR_HOLD_TRUE; // @C1 id_ = id; currentIsolationLevel_ = mapStringToLevel (initialLevel); currentCommitMode_ = mapLevelToCommitMode (currentIsolationLevel_); initialCommitMode_ = currentCommitMode_; //@AC1 (only set to *NONE if autocommit is on) if((connection_.getNewAutoCommitSupport() == 1) && (autoCommit)) //@K64 If running under new auto commit support (V5R3 and higher), by default, auto commit is run under the *NONE isolation level serverCommitMode_ = COMMIT_MODE_NONE_; //@K64 else //@K64 serverCommitMode_ = currentCommitMode_; } /** Commit the current transaction. @exception SQLException If an error occurs. **/ void commit () throws SQLException { try { DBSQLRequestDS request = null; //@P0A DBReplyRequestedDS reply = null; //@P0A try { request = DBDSPool.getDBSQLRequestDS ( //@P0C DBSQLRequestDS.FUNCTIONID_COMMIT, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA +DBSQLRequestDS.ORS_BITMAP_SQLCA, 0); // Set cursor hold. //request.setHoldIndicator (1); // @C1 request.setHoldIndicator(getHoldIndicator()); // @C1 reply = connection_.sendAndReceive (request); //@P0C int errorClass = reply.getErrorClass(); if (errorClass != 0) { int returnCode = reply.getReturnCode(); JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } } finally { if (request != null) { request.returnToPool(); request =null; } if (reply != null) { reply.returnToPool(); reply = null; } // Only errorClass used from reply } } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } resetServer (); activeLocal_ = false; // @C4C } /** Is auto-commit mode enabled?. @return true if auto-commit mode is enabled. **/ boolean getAutoCommit () { return autoCommit_; } /** Return the current commit mode. @return The commit mode. **/ // // Note: This is the only place where the commit mode is // externalized outside of this class. This is // necessary for other data streams that need to // pass a commit mode (e.g. set server attributes). // int getCommitMode () { if (serverCommitMode_ == COMMIT_MODE_CHG_) //@C6A return COMMIT_SERVER_MODE_CHG_; //@C6A else if (serverCommitMode_ == COMMIT_MODE_CS_) //@C6A return COMMIT_SERVER_MODE_CS_; //@C6A else //@C6A return serverCommitMode_; } /** * Returns the hold indicator. * @return The hold indicator. **/ int getHoldIndicator() // @C1 { return holdIndicator_; } /** Return the current transaction isolation level. @return One of the Connection.TRANSACTION_* values. **/ int getIsolation () { return currentIsolationLevel_; } boolean isGlobalActive () // @C4A { // @C4A return activeGlobal_; // @C4A } // @C4A // @C4C /** Is a local transaction active? @return true if a local transaction is active. **/ boolean isLocalActive () { return activeLocal_; } // @C4A boolean isLocalTransaction() { return localTransaction_; } // @C5D boolean isNewAutoCommitSupport() // @C5A // @C5D { // @C5A // @C5D return newAutoCommitSupport_; // @C5A // @C5D } // @C5A /** Map a transaction isolation level to its corresponding commit mode. @param level One of the java.sql.Connection.TRANSACTION_* values. @return The commit mode. @exception SQLException If the level does not map to any commit mode. **/ private static int mapLevelToCommitMode (int level) throws SQLException { int result; switch (level) { case Connection.TRANSACTION_NONE: result = COMMIT_MODE_NONE_; break; case Connection.TRANSACTION_READ_UNCOMMITTED: result = COMMIT_MODE_CHG_; break; case Connection.TRANSACTION_READ_COMMITTED: result = COMMIT_MODE_CS_; break; case Connection.TRANSACTION_REPEATABLE_READ: result = COMMIT_MODE_ALL_; break; case Connection.TRANSACTION_SERIALIZABLE: result = COMMIT_MODE_RR_; break; default: JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); result = -1; } return result; } /** Map a transaction isolation level specified as a String to its corresponding int value. @param levelAsString A transaction isolation level specified as a String. @return The int value. @exception SQLException If the String level does not map to an int value. **/ static int mapStringToLevel (String levelAsString) throws SQLException { int result; if (levelAsString.equalsIgnoreCase (JDProperties.TRANSACTION_ISOLATION_NONE)) result = Connection.TRANSACTION_NONE; else if (levelAsString.equalsIgnoreCase (JDProperties.TRANSACTION_ISOLATION_READ_COMMITTED)) result = Connection.TRANSACTION_READ_COMMITTED; else if (levelAsString.equalsIgnoreCase (JDProperties.TRANSACTION_ISOLATION_READ_UNCOMMITTED)) result = Connection.TRANSACTION_READ_UNCOMMITTED; else if (levelAsString.equalsIgnoreCase (JDProperties.TRANSACTION_ISOLATION_REPEATABLE_READ)) result = Connection.TRANSACTION_REPEATABLE_READ; else if (levelAsString.equalsIgnoreCase (JDProperties.TRANSACTION_ISOLATION_SERIALIZABLE)) result = Connection.TRANSACTION_SERIALIZABLE; else { JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); result = -1; } return result; } // @C4A /** Marks a global transaction boundary. **/ void markGlobalTransactionBoundary() { activeGlobal_ = false; } // @C2A /** Processes a commit on return indicator from a reply. If this indicator is set, it means that the transaction was committed or rolled back on the system and we should mark the transaction as not being active. @param reply The reply. **/ void processCommitOnReturn(DBBaseReplyDS reply) throws DBDataStreamException { // If the system indicates commit-on-, reflect that fact. DBReplySQLCA sqlca = reply.getSQLCA (); if (sqlca.getEyecatcherBit54()) activeLocal_ = false; // @C4C } /** Reset the system to the current commit mode. This is useful since after commits and rollbacks, the database automatically reverts back to its initial commit mode. @exception SQLException In an error occurs. **/ private void resetServer () throws SQLException { if(connection_.getNewAutoCommitSupport() == 0) //@KBA If V5R2 or earlier do what we always have { // Model the database automatically reverting back to // its initial commit mode. serverCommitMode_ = initialCommitMode_; // Reset the server's commit mode. setCommitMode (currentCommitMode_); } } void resetXAServer() throws SQLException { resetServer(); } /** Rollback the current transaction. If auto-commit mode is enabled, then do nothing. @exception SQLException If an error occurs. **/ void rollback () throws SQLException { try { DBSQLRequestDS request = null; //@P0A DBReplyRequestedDS reply = null; //@P0A try { request = DBDSPool.getDBSQLRequestDS ( //@P0C DBSQLRequestDS.FUNCTIONID_ROLLBACK, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA, 0); // Set cursor hold. //request.setHoldIndicator (1); // @C1 request.setHoldIndicator(getHoldIndicator()); // @C1 reply = connection_.sendAndReceive (request); //@P0C int errorClass = reply.getErrorClass(); if (errorClass != 0) { int returnCode = reply.getReturnCode(); JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } } finally { if (request != null) { request.returnToPool(); request =null; } if (reply != null) { reply.returnToPool(); reply = null; } // Only errorClass used from reply } } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } resetServer (); activeLocal_ = false; // @C4C } /** Set the auto-commit mode. @param autoCommit true to turn on auto-commit mode, false to turn it off. @exception SQLException If an error occurs. **/ void setAutoCommit (boolean autoCommit) throws SQLException { // If we are in a distributed transaction, then reject a request @C4A // to turn on auto-commit. If we are supposed to turn it off, @C4A // then just remember for when we are out of the distributed @C4A // transaction, since the database won't let us do any transaction @C4A // stuff during the distributed transaction. @C4A if (!localTransaction_) { // @C4A if (autoCommit == true) // @C4A JDError.throwSQLException (JDError.EXC_TXN_STATE_INVALID); // @C4A else // @C4A localAutoCommit_ = false; // @C4A } // @C4A // If we are in the local transaction, just go ahead and set it. @C4A else { // @C4A // If going from false to true, then commit any outstanding // transaction. if (!autoCommit_ && autoCommit && activeLocal_) { // @C4C commit (); connection_.postWarningSQLState (JDError.WARN_TXN_COMMITTED); } // Save the auto commit state. autoCommit_ = autoCommit; // @C5D if (newAutoCommitSupport_) { // @C5A // @C5D try { // @C5A // @C5D DBSQLAttributesDS request = new DBSQLAttributesDS( // @C5A // @C5D DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, // @C5A // @C5D id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA, 0, 0); // @C5A // @C5D request.setAutoCommit(autoCommit ? 1 : 0); // @C5A // @C5D DBReplyRequestedDS reply = connection_.sendAndReceive(request); // @C5A // @C5D int errorClass = reply.getErrorClass(); // @C5A // @C5D int returnCode = reply.getReturnCode(); // @C5A // @C5D if (errorClass != 0) // @C5A // @C5D JDError.throwSQLException(connection_, id_, errorClass, returnCode);// @C5A // @C5D } // @C5A // @C5D catch (DBDataStreamException e) { // @C5A // @C5D JDError.throwSQLException (JDError.EXC_INTERNAL, e); // @C5A // @C5D } // @C5A // @C5D } // @C5A // @C5D else // @C5A if(connection_.getNewAutoCommitSupport() == 0) //@KBA OS/400 V5R2 or earlier do what we always have setCommitMode (currentCommitMode_); else //@KBA use new auto commit support { //@KBA DBSQLAttributesDS request = null; //@KBA DBReplyRequestedDS reply = null; //@KBA try //@KBA { //@KBA request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@KBA request.setAutoCommit(autoCommit ? 0xE8 : 0xD5); //@KBA Set auto commit to on or off request.setCommitmentControlLevelParserOption(getIsolationLevel()); //@KBA Set isolation level if(autoCommit_ && connection_.getNewAutoCommitSupport() == 1) serverCommitMode_ = COMMIT_MODE_NONE_; else serverCommitMode_ = currentCommitMode_; boolean changed = setRequestLocatorPersistence(request, getIsolationLevel()); /*@ABA*/ reply = connection_.sendAndReceive(request); //@KBA int errorClass = reply.getErrorClass(); //@KBA int returnCode = reply.getReturnCode(); //@KBA if(errorClass != 0 && changed) { // Try again for the case where the server does not support the change serverAllowsLocatorPersistenceChange_ = false; request.returnToPool(); request =null; reply.returnToPool(); reply = null; request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@KBA request.setAutoCommit(autoCommit ? 0xE8 : 0xD5); //@KBA Set auto commit to on or off request.setCommitmentControlLevelParserOption(getIsolationLevel()); //@KBA Set isolation level if(autoCommit_ && connection_.getNewAutoCommitSupport() == 1) serverCommitMode_ = COMMIT_MODE_NONE_; else serverCommitMode_ = currentCommitMode_; reply = connection_.sendAndReceive(request); //@KBA errorClass = reply.getErrorClass(); //@KBA returnCode = reply.getReturnCode(); //@KBA } if (errorClass != 0) // @KBA JDError.throwSQLException(this, connection_, id_, errorClass, returnCode); // @KBA persistenceUpdated(); } //@KBA catch(DBDataStreamException e) //@KBA { //@KBA JDError.throwSQLException(JDError.EXC_INTERNAL, e); //@KBA } //@KBA finally //@KBA { //@KBA if (request != null) { request.returnToPool(); request =null;} //@KBA if (reply != null) { reply.returnToPool(); reply = null; } //@KBA } //@KBA } //@KBA } // @C4A } /* * Sets the locator persistence for a request. The persistence is typically * set to 1 (Scoped to transaction) but must be set to 0 (scoped to cursor) * if Auto commit is off and transaction isolation level isNONE. * * Should be called whenever autocommit level or isolation level is changed. * * @ABA * * This should be followed by a call to persistenceUpdated() after the * request returns successfully. This returns true if the request was * changed */ private boolean setRequestLocatorPersistence(DBSQLAttributesDS request, int commitMode) throws DBDataStreamException { // transaction isolation is none, make sure locator persistence is // scoped to the cursor requestedLocatorPersistence_ = -1; if (serverAllowsLocatorPersistenceChange_) { if (commitMode == COMMIT_MODE_NONE_) { if (currentLocatorPersistence_ != 0) { request.setLocatorPersistence(0); requestedLocatorPersistence_ = 0; return true; } } else { if (currentLocatorPersistence_ != 1) { request.setLocatorPersistence(1); requestedLocatorPersistence_ = 1; return true; } } } return false; } /* Indicate that the request to update the persistence was successful * */ private void persistenceUpdated() { if (serverAllowsLocatorPersistenceChange_ && (requestedLocatorPersistence_ != -1)) { currentLocatorPersistence_ = requestedLocatorPersistence_; } } /** Set the commit mode on the system. @param commitMode The commit mode. @exception SQLException If an error occurs. **/ private void setCommitMode (int commitMode) throws SQLException { // If auto-commit is on, then override the commit mode // to "NONE". if (autoCommit_) //@C5D && (!newAutoCommitSupport_)) // @C5C commitMode = COMMIT_MODE_NONE_; // Act only if the server commit mode is something other // then the what was requested. if (commitMode != serverCommitMode_) { JDSQLStatement sqlStatement = new JDSQLStatement ( "SET TRANSACTION ISOLATION LEVEL " + COMMIT_MODE_[commitMode]); // Send the execute immediate data stream. try { DBSQLRequestDS request = null; //@P0A DBReplyRequestedDS reply = null; //@P0A try { request = DBDSPool.getDBSQLRequestDS ( //@P0C DBSQLRequestDS.FUNCTIONID_EXECUTE_IMMEDIATE, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SQLCA, 0); boolean extended = false; //@540 if(connection_.getVRM() >= JDUtilities.vrm540) extended = true; //@540 //Bidi-HCG request.setStatementText (sqlStatement.toString (), connection_.unicodeConverter_, extended); // @C3C @P0C @540C request.setStatementText (sqlStatement.toString (), connection_.getPackageCCSID_Converter(), extended); //Bidi-HCG request.setStatementType (sqlStatement.getNativeType ()); // This statement certainly does not need a cursor, but some // versions of the system choke when none is specified. request.setCursorName ("MURCH", connection_.getConverter()); //@P0C reply = connection_.sendAndReceive (request); //@P0C int errorClass = reply.getErrorClass(); int returnCode = reply.getReturnCode(); if (errorClass != 0) JDError.throwSQLException (this, connection_, id_, errorClass, returnCode); } finally { if (request != null) { request.returnToPool(); request = null; } if (reply != null) { reply.returnToPool(); reply = null; } // Only errorClass Used from reply } } catch (DBDataStreamException e) { JDError.throwSQLException (JDError.EXC_INTERNAL, e); } serverCommitMode_ = commitMode; } } /** * Sets the cursor hold indicator. * @param hold The cursor hold value. * @exception SQLException If a database error occurs. **/ void setHoldIndicator(String hold) throws SQLException // @C1 { if (hold.equalsIgnoreCase (JDProperties.CURSORHOLD_TRUE)) holdIndicator_ = CURSOR_HOLD_TRUE; else if (hold.equalsIgnoreCase (JDProperties.CURSORHOLD_FALSE)) holdIndicator_ = CURSOR_HOLD_FALSE; else { JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); holdIndicator_ = -1; } } /** Change the transaction isolation level using one of the java.sql.Connection.TRANSACTION_* values. @param level One of the java.sql.Connection.TRANSACTION_* values with the exception of TRANSACTION_NONE. @exception SQLException If an error occurs, an invalid or unsupported level is input, or a transaction is active. **/ void setIsolation (int level) throws SQLException { // This is invalid if a transaction is active. if (activeLocal_ && connection_.getNewAutoCommitSupport() == 0) // @C4C //@KBC JDError.throwSQLException (JDError.EXC_TXN_STATE_INVALID); // @C4C // @C7D We do not allow TRANSACTION_NONE at this time. // @C7D if (level == Connection.TRANSACTION_NONE) // @C7D JDError.throwSQLException (JDError.EXC_ATTRIBUTE_VALUE_INVALID); // Save the isolation level. currentCommitMode_ = mapLevelToCommitMode (level); currentIsolationLevel_ = level; // Set the commit mode on the system. if(connection_.getNewAutoCommitSupport() == 0) //@KBA OS/400 V5R2 or earlier do what we always have setCommitMode (currentCommitMode_); else //@KBA use new auto commit and commit level support { //@KBA DBSQLAttributesDS request = null; //@KBA DBReplyRequestedDS reply = null; //@KBA int commitMode = currentCommitMode_; try //@KBA { //@KBA if(autoCommit_ && connection_.getNewAutoCommitSupport() == 1) commitMode = COMMIT_MODE_NONE_; if(serverCommitMode_ != commitMode) //@KBA { //@KBA request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@KBA request.setCommitmentControlLevelParserOption(getIsolationLevel()); //@KBA boolean changed = setRequestLocatorPersistence(request, getIsolationLevel()); /*@ABA*/ reply = connection_.sendAndReceive(request); //@KBA int errorClass = reply.getErrorClass(); //@KBA int returnCode = reply.getReturnCode(); //@KBA if (errorClass != 0 && changed) { // Retry request if this fails. serverAllowsLocatorPersistenceChange_ = false; request.returnToPool(); request =null; reply.returnToPool(); reply =null; request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@KBA request.setCommitmentControlLevelParserOption(getIsolationLevel()); //@KBA reply = connection_.sendAndReceive(request); //@KBA errorClass = reply.getErrorClass(); //@KBA returnCode = reply.getReturnCode(); //@KBA } if(errorClass != 0) //@KBA JDError.throwSQLException(this, connection_, id_, errorClass, returnCode); //@KBA persistenceUpdated(); } //@KBA } //@KBA catch(DBDataStreamException e) //@KBA { //@KBA JDError.throwSQLException(JDError.EXC_INTERNAL, e); //@KBA } //@KBA finally //@KBA { //@KBA if (request != null) { request.returnToPool(); request = null; } //@KBA if (reply != null) { reply.returnToPool(); reply = null; } //@KBA } //@KBA serverCommitMode_ = commitMode; //@KBA Note: This may not be what the user set it to, if the user want to always run auto commit with the *NONE isolation level } //@KBA } // @C4A /** Sets whether to enable the local transaction. XA support needs this to be false so that commit(), rollback(), etc. can not be called directly on this object. @param enableLocalTransaction true to enable the local transaction, false otherwise. @exception SQLException If the connection is not open or an error occurs. **/ void setLocalTransaction(boolean enableLocalTransaction) throws SQLException { localTransaction_ = enableLocalTransaction; // Auto commit is disabled while in a distributed transaction. if (localTransaction_) { autoCommit_ = localAutoCommit_; //prior to XA_START autocommit setting if(connection_.getNewAutoCommitSupport() == 0) setCommitMode(currentCommitMode_); // turn back on auto-commit else{ DBSQLAttributesDS request = null; DBReplyRequestedDS reply = null; try { request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); request.setAutoCommit( autoCommit_ ? 0xE8 : 0xD5); //@PDC change autocommit setting to prior setting before XA_START boolean changed = false; if(connection_.getNewAutoCommitSupport() == 1 && autoCommit_ == true) //@PDC { request.setCommitmentControlLevelParserOption(COMMIT_MODE_NONE_); changed = setRequestLocatorPersistence(request, COMMIT_MODE_NONE_); /*@ABA*/ serverCommitMode_ = COMMIT_MODE_NONE_; } reply = connection_.sendAndReceive(request); int errorClass = reply.getErrorClass(); int returnCode = reply.getReturnCode(); if (errorClass != 0 && changed) { // Retry request if this fails. serverAllowsLocatorPersistenceChange_ = false; request.returnToPool(); request = null; reply.returnToPool(); reply =null; request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); request.setAutoCommit( autoCommit_ ? 0xE8 : 0xD5); //@PDC change autocommit setting to prior setting before XA_START if(connection_.getNewAutoCommitSupport() == 1 && autoCommit_ == true) //@PDC { request.setCommitmentControlLevelParserOption(COMMIT_MODE_NONE_); serverCommitMode_ = COMMIT_MODE_NONE_; } reply = connection_.sendAndReceive(request); errorClass = reply.getErrorClass(); returnCode = reply.getReturnCode(); } if(errorClass != 0) JDError.throwSQLException(this, connection_, id_, errorClass, returnCode); persistenceUpdated(); } catch(DBDataStreamException e) { JDError.throwSQLException(JDError.EXC_INTERNAL, e); } finally { if (request != null) { request.returnToPool(); request = null; } if (reply != null) { reply.returnToPool(); reply = null; } // Only errorClass used from reply } } } else { localAutoCommit_ = autoCommit_; autoCommit_ = false; if(connection_.getNewAutoCommitSupport() == 0) //@KBA System is v5r2 or less, do what we always have setCommitMode(currentCommitMode_); else //@KBA { DBSQLAttributesDS request = null; //@KBA DBReplyRequestedDS reply = null; //@KBA try //@KBA { //@KBA //auto commit is always false when we are in here so we will run under default or specified isolation level request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@KBA request.setAutoCommit(0xD5); //@KBA turn off auto commit if(serverCommitMode_ != currentCommitMode_) //@KBA request.setCommitmentControlLevelParserOption(getIsolationLevel()); //@KBA boolean changed = setRequestLocatorPersistence(request, getIsolationLevel()); /*@ABA*/ reply = connection_.sendAndReceive(request); //@KBA int errorClass = reply.getErrorClass(); //@KBA int returnCode = reply.getReturnCode(); //@KBA if (errorClass != 0 && changed) { // Retry request if this fails. serverAllowsLocatorPersistenceChange_ = false; request.returnToPool(); request = null; reply.returnToPool(); reply = null; request = DBDSPool.getDBSQLAttributesDS (DBSQLAttributesDS.FUNCTIONID_SET_ATTRIBUTES, id_, DBBaseRequestDS.ORS_BITMAP_RETURN_DATA + DBBaseRequestDS.ORS_BITMAP_SERVER_ATTRIBUTES, 0); //@KBA request.setAutoCommit(0xD5); //@KBA turn off auto commit if(serverCommitMode_ != currentCommitMode_) //@KBA request.setCommitmentControlLevelParserOption(getIsolationLevel()); //@KBA reply = connection_.sendAndReceive(request); //@KBA errorClass = reply.getErrorClass(); //@KBA returnCode = reply.getReturnCode(); //@KBA } if(errorClass != 0) //@KBA JDError.throwSQLException(this, connection_, id_, errorClass, returnCode); //@KBA persistenceUpdated(); } //@KBA catch(DBDataStreamException e) //@KBA { //@KBA JDError.throwSQLException(JDError.EXC_INTERNAL, e); //@KBA } //@KBA finally //@KBA { //@KBA if (request != null) { request.returnToPool(); request = null; } //@KBA if (reply != null) { reply.returnToPool(); reply = null; } //@KBA } //@KBA serverCommitMode_ = currentCommitMode_; //@KBA } } } // @C5D void setNewAutoCommitSupport(boolean newAutoCommitSupport) // @C5A // @C5D throws SQLException // @C5A // @C5D { // @C5A // @C5D newAutoCommitSupport_ = newAutoCommitSupport; // @C5A // @C5D // @C5A // @C5D if (newAutoCommitSupport) // @C5A // @C5D setAutoCommit (true); // @C5A // @C5D // The default - but we have to send it now // @C5A // @C5D // so that the system nows we want to use // @C5A // @C5D // the new support. // @C5A // @C5D } // @C5A /** Take note that a statement has been executed. **/ void statementExecuted () { if (localTransaction_) // @C4A activeLocal_ = ! autoCommit_; else // @C4A activeGlobal_ = true; // @C4A } //@KBA /** Returns the isolation/commit level to send to the system. **/ private int getIsolationLevel() { int isolationLevel = currentCommitMode_; //Server commit mode level is different than clients so map client commit level to appropriate server commit level if(isolationLevel == COMMIT_MODE_CHG_) isolationLevel = COMMIT_SERVER_MODE_CHG_; else if(isolationLevel == COMMIT_MODE_CS_) isolationLevel = COMMIT_SERVER_MODE_CS_; //if auto commit is on and user specified false for 'true autocommit property' or by default run under *NONE isolation level if(autoCommit_ && connection_.getNewAutoCommitSupport() == 1) isolationLevel = COMMIT_MODE_NONE_; return isolationLevel; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy