Beispiel #1
0
        }         // getBranchQualifier

        /*
        ** Name: Equals
        **
        ** Description:
        **	Determine if this Xid is identical to another Xid.
        **
        ** Input:
        **	xid	Xid to compare.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	boolean	True if identical, False otherwise.
        **
        ** History:
        **	15-Mar-01 (gordy)
        **	    Created.
        **	29-Sep-03 (thoda04)
        **	    Port to .NET provider.
        */

        /// <summary>
        /// Determine if this Xid is identical to another Xid.
        /// </summary>
        /// <param name="xid"></param>
        /// <returns></returns>
        public virtual bool Equals(AdvanXID xid)
        {
            if (xid == null)
            {
                return(false);
            }

            if (this == xid)
            {
                return(true);
            }
            if (fid != xid.FormatId)
            {
                return(false);
            }

            byte[] gtid  = xid.getGlobalTransactionId();
            byte[] bqual = xid.getBranchQualifier();

            if (this.gtid.Length != gtid.Length ||
                this.bqual.Length != bqual.Length)
            {
                return(false);
            }

            for (int i = 0; i < gtid.Length; i++)
            {
                if (this.gtid[i] != gtid[i])
                {
                    return(false);
                }
            }

            for (int i = 0; i < bqual.Length; i++)
            {
                if (this.bqual[i] != bqual[i])
                {
                    return(false);
                }
            }

            return(true);
        }          // Equals
Beispiel #2
0
            /*
            ** Name: readXids
            **
            ** Description:
            **	Query DBMS for transaction IDs.
            **
            ** Input:
            **	db	    Database name.
            **
            ** Output:
            **	None.
            **
            ** Returns:
            **	AdvanXID[]   Transaction IDs.
            **
            ** History:
            **	18-Apr-01 (gordy)
            **	    Created.*/
            internal virtual AdvanXID[] readXids(String db)
            {
                lock(this)
                {
                    xids.Clear();
                    msg.LockConnection();
                    try
                    {
                        msg.begin(MSG_REQUEST);
                        msg.write(MSG_REQ_2PC_XIDS);
                        msg.write(MSG_RQP_DB_NAME);
                        msg.write(db);
                        msg.done(true);
                        readResults();
                    }
                    catch (SqlEx ex)
                    {
                        if (trace.enabled(1))
                            trace.log("readXids(): failed!");
                        if (trace.enabled(1))
                            ex.trace(trace);
                        throw;
                    }
                    finally
                    {
                        msg.UnlockConnection();
                    }

                    /*
                    ** XIDs have been collected in xids.
                    ** Allocate and populate the XID array.
                    */
                    AdvanXID[] xid = new AdvanXID[xids.Count];

                    int i=0;
                    foreach(Object obj in xids)
                    {
                        xid[i++] = (AdvanXID) obj;
                    }

                    xids.Clear();
                    return (xid);
                }
            }
Beispiel #3
0
        /*
        ** Name: driver_parms
        **
        ** Description:
        **	Send internal DAM-ML connection parameters.
        **
        ** Input:
        **	local	Use local user ID.
        **	timeout	Connection timeout.
        **	xa_xid	XA transaction ID.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	void.
        **
        ** History:
        **	 4-Nov-99 (gordy)
        **	    Send timeout connection parameter to server.
        **	11-Apr-01 (gordy)
        **	    Added timeout parameter to replace DriverManager reference.
        **	18-Apr-01 (gordy)
        **	    Added support for Distributed Transaction Management Connections.
        **	06-Dec-02 (wansh01)
        **	    Added support for optional userid for local connection.
        **	    set connection parameter MSG_CP_LOGIN_TYPE to MSG_CPV_LOGIN_USER
        **	    (an internal value) if no userid specified for local connection.
        **	26-Dec-02 (gordy)
        **	    Send initial autocommit state to server.
        **	15-Jan-03 (gordy)
        **	    Extracted from connect().  Added local user, host name & address.
        **	 7-Jul-03 (gordy)
        **	    Write all parameters associated with local user connections.
        **	 6-jul-04 (gordy; ported by thoda04)
        **	    Added session_mask to password encryption.
        */
        private void driver_parms( bool local, int timeout, AdvanXID xa_xid )
        {
            String value, userID = null;

            /*
            ** User ID needed for various parameters.
            */
            try { userID = Environment.UserName; }
            catch( Exception /*ignore*/ ) {}
            if ( userID != null  &&  userID.Length == 0 )  userID = null;

            /*
            ** If connection should be made for local user, send the
            ** appropriate connection parameters. (protocol level
            ** checked by caller).
            */
            if ( local  &&  userID != null )
            {
                /*
                ** A special login type is used to indicate that
                ** the local user ID of the client should be used
                ** (without requiring a password) to establish
                ** the connection.
                */
                if ( trace.enabled( 3 ) )  trace.write( "    Login Type: 'user'" );

                msg.write( MSG_CP_LOGIN_TYPE );
                msg.write( (short)1 );
                msg.write( MSG_CPV_LOGIN_USER);

                /*
                ** If a user ID had been provided, then we would not be
                ** doing a local user connection.  Also, a password is
                ** only sent if a user ID is provided.  These parameters
                ** are hijacked for this case to send the local user ID
                ** with some verification of its authenticity.
                */
                msg.write( MSG_CP_USERNAME );
                msg.write( userID );
                msg.write( MSG_CP_PASSWORD );
                msg.write( msg.encode( userID, conn.session_mask, userID ) );
            }

            /*
            ** timeout of 0 means no timeout (full blocking).
            ** Only send timeout if non-blocking.
            */
            if ( timeout != 0 )
            {
                if ( trace.enabled( 3 ) )
                    trace.write( "    Timeout: " + timeout );
                /*
                ** Ingres driver interprets a negative timeout
                ** as milli-seconds.  Otherwise, convert seconds to
                ** milli-seconds.
                */
                timeout = (timeout < 0) ? -timeout : timeout * 1000;
                msg.write( MSG_CP_TIMEOUT );
                msg.write( (short)4 );
                msg.write( timeout );
            }

            if ( xa_xid != null  &&  xa_xid.Type == AdvanXID.XID_XA  &&
                conn.msg_protocol_level >= MSG_PROTO_2 )
            {
                if ( trace.enabled( 3 ) )
                    trace.write( "    XA Transaction ID: " + xa_xid );

                msg.write( MSG_CP_XA_FRMT );
                msg.write( (short)4 );
                msg.write( xa_xid.FormatId );
                msg.write( MSG_CP_XA_GTID );
                msg.write( xa_xid.getGlobalTransactionId() );
                msg.write( MSG_CP_XA_BQUAL );
                msg.write( xa_xid.getBranchQualifier() );

                /*
                ** Autocommit is disabled when connecting to
                ** an existing distributed transaction.
                */
                autoCommit = false;
            }

            if ( conn.msg_protocol_level >= MSG_PROTO_3 )
            {
                /*
                ** Force initial autocommit state rather than relying
                ** on the server default.
                */
                if ( trace.enabled( 3 ) )
                    trace.write( "    Autocommit State: " +
                        (autoCommit ? "on" : "off") );

                msg.write( MSG_CP_AUTO_STATE );
                msg.write( (short)1 );
                msg.write( (byte)(autoCommit ? MSG_CPV_POOL_ON
                    : MSG_CPV_POOL_OFF) );

                /*
                ** Provide local user ID
                */
                if ( userID != null )
                {
                    if ( trace.enabled( 3 ) )
                        trace.write( "    Local User ID: " + userID );

                    msg.write( MSG_CP_CLIENT_USER );
                    msg.write( userID );
                }

                /*
                ** Provide local host name
                */
                value = msg.LocalHost;
                if ( value != null  &&  value.Length > 0 )
                {
                    if ( trace.enabled( 3 ) )
                        trace.write( "    Local Host: " + value );

                    msg.write( MSG_CP_CLIENT_HOST );
                    msg.write( value );
                }

                /*
                ** Provide local host address
                */
                value = msg.LocalAddress;
                if ( value != null  &&  value.Length > 0 )
                {
                    if ( trace.enabled( 3 ) )
                        trace.write( "    Local Address: " + value );

                    msg.write( MSG_CP_CLIENT_ADDR );
                    msg.write( value );
                }
            }  // end if MSG_PROTO_3

            return;
        }
Beispiel #4
0
        /*
        ** Name: dbms_connect
        **
        ** Description:
        **	Establish connection with DBMS.
        **
        ** Input:
        **	info	Connection property list.
        **	xid	Distributed transaction ID.
        **	timeout	Connection timeout.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	void.
        **
        ** History:
        **	28-Mar-01 (gordy)
        **	    Separated from constructor.
        **	11-Apr-01 (gordy)
        **	    Added timeout parameter to replace DriverManager reference.
        **	18-Apr-01 (gordy)
        **	    Added support for Distributed Transaction Management Connections.
        **	10-May-01 (gordy)
        **	    Check DBMS capabilities relevant to driver configuration.
        **	20-Aug-01 (gordy)
        **	    Added connection parameter for default cursor mode.
        **	20-Feb-02 (gordy)
        **	    Added dbmsInfo checks for DBMS type and protocol level.
        **	 1-Mar-07 (gordy, ported by thoda04)
        **	    Check connection character encoding and property override.
        */
        private void dbms_connect(IConfig config, int timeout, AdvanXID xa_xid)
        {
            /*
            ** Check if character encoding has been established
            ** for the connection.  If not, it may be explicitly
            ** set via driver properties.  Encoding must be set
            ** before connection parameters are processed.
            */
            String encodingName = config.get(DrvConst.DRV_PROP_ENCODE);

            if (encodingName != null && encodingName.Length != 0)
            {
                // encodingName was checked to be valid in ParseConnectionString
                System.Text.Encoding encoding =
                    System.Text.Encoding.GetEncoding(encodingName);
                try
                {
                    msg.setCharSet(
                        new CharSet(encoding, true, "CharacterEncoding", encodingName));
                    if (trace.enabled(1))
                        trace.write(tr_id + ": encoding: " +
                            encodingName + " (" + encoding.ToString() +
                            ",WindowsCodePage=" + encoding.WindowsCodePage.ToString()
                            + ")");
                }
                catch (Exception)
                {
                    if (trace.enabled(1))
                        trace.write(tr_id + ": unknown encoding: " + encodingName);
                    throw SqlEx.get(ERR_GC4009_BAD_CHARSET);
                }
            }
            else if (msg.getCharSet() == null)
            {
                if (trace.enabled())
                    trace.log(title + ": failed to establish character encoding!");
                throw SqlEx.get(ERR_GC4009_BAD_CHARSET);
            }

            if (trace.enabled(2))
                trace.write(tr_id + ": Connecting to database");

            try
            {
                /*
                ** Send connection request and parameters.
                */
                msg.begin(MSG_CONNECT);
                client_parms ( config );
                driver_parms( checkLocalUser( config ), timeout, xa_xid );
                msg.done( true );
                readResults();
            }
            catch ( SqlEx ex )
            {
                if (trace.enabled(1))
                    trace.write(tr_id + ": error connecting to database:" +
                        ex.Message);
                conn.close();
                throw;
            }
        }
Beispiel #5
0
        /*
        ** Name: startTransaction
        **
        ** Description:
        **	Start a distributed transaction.  No transaction, autocommit
        **	or normal, may be active.
        **
        ** Input:
        **	xid	XID.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	void.
        **
        ** History:
        **	21-Mar-01 (gordy)
        **	    Created.
        **	28-Mar-01 (gordy)
        **	    Check protocol level for server support.
        **	 2-Apr-01 (gordy)
        **	    Use AdvanXID, support Ingres transaction ID.
        **	11-Apr-01 (gordy)
        **	    Trace transaction ID.
        **	18-Apr-01 (gordy)
        **	    Added support for Distributed Transaction Management Connections.*/
        internal virtual void startTransaction(AdvanXID xid, int flags)
        {
            warnings = null;

            if (trace.enabled())
            {
                trace.log(title + ".startTransaction( " + xid + ", 0x" +
                         Convert.ToString(flags, 16) + " )");
            }

            if (conn.is_dtmc)
            {
                if (trace.enabled(1))
                    trace.write(tr_id + ": not permitted when DTMC");
                throw SqlEx.get( ERR_GC4019_UNSUPPORTED );
            }

            if (conn.msg_protocol_level < MSG_PROTO_2 ||
                (flags != 0 && conn.msg_protocol_level < MSG_PROTO_5))
            {
                if (trace.enabled(1))
                    trace.write(tr_id + ": protocol = " + conn.msg_protocol_level);
                throw SqlEx.get( ERR_GC4019_UNSUPPORTED );
            }

            switch (xid.Type)
            {
                case AdvanXID.XID_INGRES:
                case AdvanXID.XID_XA:
                    // OK!
                    break;

                default:
                    if (trace.enabled(1))
                        trace.write(tr_id + ": unknown XID type: " + xid.Type);
                    throw SqlEx.get( ERR_GC4019_UNSUPPORTED );

            }

            msg.LockConnection();
            try
            {
                msg.begin(MSG_XACT);
                msg.write(MSG_XACT_BEGIN);

                switch (xid.Type)
                {
                    case AdvanXID.XID_INGRES:
                        msg.write(MSG_XP_II_XID);
                        msg.write((short) 8);
                        msg.write((int) xid.XId);
                        msg.write((int) (xid.XId >> 32));
                        break;

                    case AdvanXID.XID_XA:
                        msg.write(MSG_XP_XA_FRMT);
                        msg.write((short) 4);
                        msg.write(xid.FormatId);
                        msg.write(MSG_XP_XA_GTID);
                        msg.write(xid.getGlobalTransactionId());
                        msg.write(MSG_XP_XA_BQUAL);
                        msg.write(xid.getBranchQualifier());

                        if (flags != 0)
                        {
                            msg.write(MSG_XP_XA_FLAGS);
                            msg.write((short)4);
                            msg.write(flags);
                        }
                        break;

                }

                msg.done(true);
                readResults();
            }
            catch (SqlEx ex)
            {
                if (trace.enabled())
                    trace.log(title + ".startTransaction(): error starting xact");
                if (trace.enabled(1))
                    ex.trace(trace);
                throw ex;
            }
            finally
            {
                msg.UnlockConnection();
            }

            return ;
        }
Beispiel #6
0
 /*
 ** Name: startTransaction
 **
 ** Description:
 **	Start a distributed transaction.  No transaction, autocommit
 **	or normal, may be active.
 **
 ** Input:
 **	xid	XA XID.
 **
 ** Output:
 **	None.
 **
 ** Returns:
 **	void.
 **
 ** History:
 **	20-Jul-06 (gordy)
 **	    Created.
 */
 /// <summary>
 /// Start work on behalf of a Distributed Transaction branch.
 /// </summary>
 /// <param name="xid"></param>
 internal void startTransaction(AdvanXID xid)
 {
     startTransaction(xid, 0);
     return;
 }
Beispiel #7
0
        /*
        ** Name: Enlist
        **
        ** Description:
        **	Enlist in the Microsoft Distributed Transaction Coordinator (MSDTC).
        **	Called by Connection.EnlistDistributedTransaction(ITransaction).
        **
        ** History:
        **	01-Oct-03 (thoda04)
        **	    Created.
        */
        /// <summary>
        /// Enlist in the Microsoft Distributed Transaction Coordinator (MSDTC).
        /// </summary>
        /// <param name="advanConnection">Internal connection.</param>
        /// <param name="tx">ITransaction interface of object.</param>
        /// <param name="nv">Connection string parameter values list.</param>
        internal void Enlist(
			AdvanConnect advanConnection,
			ITransaction tx,
			ConnectStringConfig nv)
        {
            this.advanConnect = advanConnection;
            this.Transaction = tx;

            trace.write(3, title + ": Enlist()");
            if (debugging)
                Console.WriteLine(title + ": Enlist() begins...");

            /*
            Call DtcGetTransactionManager in MS DTC proxy to
            establish a connection to the Transaction Manager.
            From the TM, get the XATM's Single Pipe Helper interface
            that will help establish an enlistment in MSDTC
            using the XA protocol (XaSwitch and XIDs).
            */
            XaHelperSinglePipe = GetDtcToXaHelperSinglePipe();

            /*
            Obtain the Resource Manager (RM) cookie.  The XARMCreate
            method is invoked once per connection.  The information provided
            makes it possible for the transaction manager to connect to the
            database to perform recovery.  The transaction manager durably records
            this information in it's log file.  If recovery is necessary, the
            transaction manager reads the log file, reconnects to the database,
            and initiates XA recovery.

            Calling XARMCreate results in a message from the DTC proxy
            to the XA Transaction Manager (TM).  When the XA TM receives a message that
            contains the DSN and the name of the client DLL, TM will:
               1) LoadLibrary the client dll (Ingres.Support.dll which will
                  drag in the referenced Ingres.ProviderInternals from the GAC).
               2) GetProcAddress the GetXaSwitch function in the dll.
               3) Call the GetXaSwitch function to obtain the XA_Switch.
               4) Call the xa_open function to open an XA connection with the
                  resource manager (Ingres).  When the our xa_open function is called,
                 the DTC TM passes in the DSN parm as the OPEN_STRING.  It then
                 closes the connection by calling xa_close.  (It's just testing
                 the connection information so that it won't be surprised
                 when it's in the middle of recovery later.)
               5) Generate a RM GUID for the connection.
               6) Write a record to the DTCXATM.LOG file indicating that a new
                 resource manager is being established.  The log record contains
                 the DSN parm, the name of our RM (Ingres.Support.dll), and
                 the RM GUID.  This information will be used to reconnect to
                 Ingres should recovery be necessary.

            XARMCreate method also causes the MS DTC proxy to create a resource
            manager object and returns an opaque pointer to that object as
            the RMCookie.  This RMCookie represents the connection to the TM.
            */

            nv = new ConnectStringConfig(nv);  // create a working copy
            // Connection attempts with MSG_P_DTMC will raise error:
            //    GC000B_RMT_LOGIN_FAIL Login failure: invalid username/password
            // if you try to send login information
            nv.Remove(DrvConst.DRV_PROP_USR);   // remove "user="******"password="******"group="
            nv.Remove(DrvConst.DRV_PROP_ROLE);  // remove "role="

            string xa_open_string = ConnectStringConfig.ToConnectionString(nv);
            int trace_level = trace.getTraceLevel("XA");
            if (trace_level > 0)
            {
                xa_open_string +=  // tell MSDTC process to trace XASwitch
                    ";Trace=XA;TraceLevel=" + trace_level.ToString();
            }

            // Locate the Ingres.Support.dll that holds our XASwitch
            // support.  The dll should be in the GAC so use a type from
            // the Ingres.Support assembly, qualified by the same
            // Version and PublicKeyToken that the currently executing
            // Ingres.Support assembly is using.
            System.Reflection.Assembly assembly =
                System.Reflection.Assembly.GetExecutingAssembly();
            string fullname = assembly.FullName;
            string version;
            int index = fullname.IndexOf(',');  // locate ", Verison=..."
            if (index != -1)
                version = fullname.Substring(index);
            else  // should not happen unless in a debugging environment
                version = ", Version=2.0.0.0, Culture=neutral" +
                          ", PublicKeyToken=1234567890123456";

            Type type = Type.GetType(
                "Ingres.Support.XAProvider" +
                ", Ingres.Support" + version);
            // BTW, type will be null if Ingres.Support is not properly
            // in the GAC or has a different version number from
            // Ingres.Client.  A NullReferenceException would follow.
            string dll = type.Assembly.Location;

            XaHelperSinglePipe_XARMCreate(
                xa_open_string,
                dll,
                out this.RMCookie);

            /*
            Obtain an XID from an ITransaction interface pointer.
            The ITransaction pointer is offered by a transaction object.
            The transaction object contains a DTC transaction that is
            identified by a transaction identifier (TRID) which is a globally
            unique identifier (GUID).  Given a TRID, one can always create an XID.
            The MS DTC proxy generates an XID and returns it.

            Into the XID's formatID, MS puts 0x00445443 ("DTC").
            Into the XID's gtrid (length=0x10), MS puts a GUID
            identifying the global transaction identifier.  (Same as
            Transaction.Current.TransactionInformation.DistributedIdentifier.)
            Into the XID's bqual (length=0x30), MS puts a second
            GUID identifying the TM that is coordinating the transaction
            and also a third GUID identifying the database connection.
            If two components in the same transaction have their own connections,
            then they will be loosely coupled XA threads of control (different
            bquals).  MS goes beyond the XA spec and expects that the two
            loosely coupled threads will not deadlock on resource locks.
            */
            XAXIDStruct xaXIDstruct = new XAXIDStruct(-1,0,0,new byte[128]);

            XaHelperSinglePipe_ConvertTridToXID(
                Transaction, this.RMCookie, ref xaXIDstruct);
            advanXID = new AdvanXID(xaXIDstruct);

            /*
            Tell the DTC proxy to enlist on behalf of the XA resource manager.
            EnlistWithRM is called for every transaction that the connection
            is requested to be enlisted in. The provider is responsible for
            implementing the ITransactionResourceAsync interface.  This
            interface includes the PrepareRequest, CommitRequest, AbortRequest,
            and TMDown callbacks.  The transaction manager will invoke these
            callback methods to deliver phase one and phase two notifications
            to the provider.
            The MS DTC proxy informs the transaction manager that the provider
            wishes to enlist in the transaction.  The transaction
            manager creates an internal enlistment object to record the fact
            that the provider is participating in the transaction.
            Upon return from EnlistWithRM, the MS DTC proxy will have created
            an enlistment object and returns the pITransactionEnlistmentAsync
            interface pointer of the enlistment object back to the provider.
            */

            try
            {
            StartMSDTCRequest(MSDTCRequest.ENLIST);  // start worker thread

            if (EnlistmentException != null)
                throw EnlistmentException;

            // wait until EnlistWithRM is completed under the worker thread
            advanConnect.msg.LockConnection();
            advanConnect.msg.UnlockConnection();

            advanConnect.startTransaction(advanXID);
            TxBranchState = TXBRANCHSTATE.Active;
            }
            catch
            {
                // release our bad connection to MS DTC and
                // shutdown our worker thread to MS DTC.
                XaHelperSinglePipe_ReleaseRMCookie(ref this.RMCookie);
                StartMSDTCRequest(MSDTCRequest.DELIST);
                throw;
            }

            // At this point we have a good MSDTC enlistment!

            // The advanConnect internal connection object is now being used by
            // two threads: the application thread and the MSDTC proxy thread.
            // The advanConnect usage count will block release of the internal
            // connection advanConnect object back into the connection pool
            // until each is finished and calls
            // advanConnect.CloseOrPutBackIntoConnectionPool() method.
            // See IngresConnection.Open() method for application's claim stake.
            advanConnect.ReferenceCountIncrement();  // MSDTC proxy thread stakes it claim

            trace.write(3, title + ": Enlist() complete");
            if (debugging)
                Console.WriteLine(title + ": Enlist() complete");
        }
Beispiel #8
0
 /*
 ** Name: commit
 **
 ** Description:
 **	Commit XA transaction.
 **
 ** Input:
 **	xid	XA XID.
 **
 ** Output:
 **	None.
 **
 ** Returns:
 **	void
 **
 ** History:
 **	20-Jul-06 (gordy, ported by thoda04 05-Mar-09)
 **	    Created.
 */
 /// <summary>
 /// Commit work done on behalf of a Distributed Transaction branch.
 /// </summary>
 /// <param name="xid"></param>
 internal void commit(AdvanXID xid)
 {
     commit(xid, 0);
     return;
 }
Beispiel #9
0
        /*
        ** Name: Equals
        **
        ** Description:
        **	Determine if this Xid is identical to another Xid.
        **
        ** Input:
        **	xid	Xid to compare.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	boolean	True if identical, False otherwise.
        **
        ** History:
        **	15-Mar-01 (gordy)
        **	    Created.
        **	29-Sep-03 (thoda04)
        **	    Port to .NET provider.
        */
        /// <summary>
        /// Determine if this Xid is identical to another Xid.
        /// </summary>
        /// <param name="xid"></param>
        /// <returns></returns>
        public virtual bool Equals(AdvanXID xid)
        {
            if (xid == null)
                return false;

            if (this == xid)
                return (true);
            if (fid != xid.FormatId)
                return (false);

            byte[] gtid  = xid.getGlobalTransactionId();
            byte[] bqual = xid.getBranchQualifier();

            if (this.gtid.Length != gtid.Length ||
                this.bqual.Length != bqual.Length)
                return (false);

            for (int i = 0; i < gtid.Length; i++)
                if (this.gtid[i] != gtid[i])
                    return (false);

            for (int i = 0; i < bqual.Length; i++)
                if (this.bqual[i] != bqual[i])
                    return (false);

            return (true);
        }
Beispiel #10
0
        /*
        ** Name: xa_start   -  Start/Resume binding a thread w/an XID.
        **
        ** Description:
        **
        ** Inputs:
        **      xid        - pointer to XID.
        **      rmid       - RMI identifier, assigned by the TP system, unique to the AS
        **                   process.
        **      flags      - TP system-specified flags, one of
        **                       TMJOIN/TMRESUME/TMNOWAIT/TMASYNC/TMNOFLAGS.
        **
        ** Outputs:
        **	Returns:
        **          XA_OK          - normal execution.
        **          XA_RETRY       - if TMNOWAIT is set in flags. We will *always*
        **                           assume a blocking call and return this (Ingres65).
        **          XA_RB*         - if this XID is marked "rollback only".
        **             XA_RBROLLBACK - rollback only, unspecified reason.
        **             XA_RBCOMMFAIL - on any error on a GCA call.
        **             XA_RBDEADLOCK - deadlock detected down in DBMS server.
        **             XA_RBINTEGRITY- integrity violation detected in DBMS server.
        **             XA_RBOTHER    - any other reason for rollback.
        **             XA_RBPROTO    - protocol error, this XA call made in wrong state
        **                             for the thread/RMI.
        **             XA_RBTIMEOUT  - the local xn bound to this XID timed out.
        **             XA_RBTRANSIENT- a transient error was detected by the DBMS svr.
        **          XAER_ASYNC     - if TMASYNC was specified. We don't support
        **                           TMASYNC (post-Ingres65 feature).
        **          XAER_RMERR     - internal error w/gca association mgmt.
        **          XAER_RMFAIL    - RMI made unavailable by some error.
        **          XAER_DUPID     - XID already exists, when it's not expected to be
        **                           "known" at this AS, i.e. it's not TMRESUME/TMJOIN.
        **          XAER_OUTSIDE   - RMI/thread is doing work "outside" of global xns.
        **          XAER_NOTA      - TMRESUME or TMJOIN was set, and XID not "known".
        **          XAER_INVAL     - illegal input arguments.
        **          XAER_PROTO     - if there are active/suspended XIDs bound to
        **                           the RMI. Enforces XA Spec's "state table" rules.
        **
        ** History:
        **	18-Aug-03 (thoda04)
        **	    Created.  Rich description copied from front/embed/libqxa.
        */
        /// <summary>
        /// Start work on behalf of a transaction branch.
        /// </summary>
        /// <param name="xid">XID to perform the work on.</param>
        /// <param name="rmid">An integer, assigned by the transaction manager,
        /// uniquely identifies the called resource manager within the thread
        /// of control.</param>
        /// <param name="flags"></param>
        /// <returns>XA_OK for normal execution or an XAER* error code.</returns>
        public int xa_start(
			AdvanXID xid,
			int rmid,
			long flags)
        {
            if (xid == null)
            {
                trace.write("xa_start: xid = <null>"+
                    ", rmid = " + rmid.ToString());
                return XAER_INVAL;  // invalid arguments were specified
            }

            if (trace.enabled(3))
            {
                trace.write("xa_start: xid = " + xid.ToString() +
                    ", rmid = " + rmid.ToString() +
                    ", flags = " + XAFlagsToString(flags));
            }

            return XAER_PROTO;  // unexpected context
        }
Beispiel #11
0
        /*
        ** Name: xa_rollback   -  Propagate rollback of a local xn bound to an XID.
        **
        ** Description:
        **
        ** Inputs:
        **      xid        - pointer to XID.
        **      rmid       - RMI identifier, assigned by the TP system, unique to the
        **                   AS process w/which LIBQXA is linked in.
        **      flags      - TP system-specified flags, one of TMASYNC/TMNOFLAGS.
        **
        ** Outputs:
        **	Returns:
        **          XA_OK          - normal execution.
        **          XA_RB*         - if this XID is marked "rollback only".
        **             XA_RBROLLBACK - rollback only, unspecified reason.
        **             XA_RBCOMMFAIL - on any error on a GCA call.
        **             XA_RBDEADLOCK - deadlock detected down in DBMS server.
        **             XA_RBINTEGRITY- integrity violation detected in DBMS server.
        **             XA_RBOTHER    - any other reason for rollback.
        **             XA_RBPROTO    - protocol error, this XA call made in wrong state
        **                             for the thread/RMI.
        **             XA_RBTIMEOUT  - the local xn bound to this XID timed out.
        **             XA_RBTRANSIENT- a transient error was detected by the DBMS
        **                             server.
        **          XAER_ASYNC     - if TMASYNC was specified. We don't support
        **                           TMASYNC (Ingres65).
        **          XAER_RMERR     - internal error w/gca association mgmt.
        **          XAER_RMFAIL    - RMI made unavailable by some error.
        **          XAER_NOTA      - TMRESUME or TMJOIN was set, and XID not "known".
        **          XAER_INVAL     - illegal arguments.
        **          XAER_PROTO     - if there are active/suspended XIDs bound to
        **                           the RMI. Enforces XA Spec's "state table" rules.
        **
        **          UNSUPPORTED in Ingres65
        **          -----------------------
        **
        **          XA_HEURHAZ     - Work done in global xn branch may have been
        **                           heuristically completed.
        **          XA_HEURCOM     - Work done may have been heuristically committed.
        **          XA_HEURRB      - Work done was heuristically rolled back.
        **          XA_HEURMIX     - Work done was partially committed and partially
        **                           rolled back heuristically.
        **
        ** History:
        **	18-Aug-03 (thoda04)
        **	    Created.  Rich description copied from front/embed/libqxa.
        */
        /// <summary>
        /// Roll back the work on behalf of a transaction branch.
        /// </summary>
        /// <param name="xid">XID to perform the work on.</param>
        /// <param name="rmid">An integer, assigned by the transaction manager,
        /// uniquely identifies the called resource manager within the thread
        /// of control.</param>
        /// <param name="flags"></param>
        /// <returns>XA_OK for normal execution or an XAER* error code.</returns>
        public int xa_rollback(
			AdvanXID xid,
			int rmid,
			long flags)
        {
            if (xid == null)
            {
                trace.write("xa_rollback: xid = <null>"+
                    ", rmid = " + rmid.ToString());
                return XAER_INVAL;  // invalid arguments were specified
            }

            if (trace.enabled(3))
            {
                trace.write("xa_rollback: xid = " + xid.ToString() +
                    ", rmid = " + rmid.ToString() +
                    ", flags = " + XAFlagsToString(flags));
            }

            int rc = xa_commit_or_rollback(false, xid, rmid, flags);
            return rc;
        }
Beispiel #12
0
        /*
        ** Name: xa_recover   -  Recover a set of prepared XIDs for a specific RMI.
        **
        ** Description:
        **
        ** Inputs:
        **      xids       - pointer to XID list.
        **      count      - maximum number of XIDs expected by the TP system.
        **      rmid       - RMI identifier, assigned by the TP system, unique to the AS
        **                   process w/which LIBQXA is linked in.
        **      flags      - TP system-specified flags, one of
        **                          TMSTARTRSCAN/TMENDRSCAN/TMNOFLAGS.
        **
        ** Outputs:
        **	Returns:
        **          list of AdvanXID's or an empty list
        **	XaSwitch.xa_recover will return
        **          >= 0           - number of XIDs returned.
        **          XAER_RMERR     - internal error w/gca association mgmt.
        **          XAER_RMFAIL    - RMI made unavailable by some error.
        **          XAER_INVAL     - illegal arguments.
        **          XAER_PROTO     - if there are active/suspended XIDs bound to
        **                           the RMI. Enforces XA Spec's "state table" rules.
        **
        ** History:
        **	18-Aug-03 (thoda04)
        **	    Created.  Rich description copied from front/embed/libqxa.
        */
        /// <summary>
        /// Obtain a list of prepared transaction branches from a resource manager.
        /// </summary>
        /// <param name="xids">Output area to place XIDs.</param>
        /// <param name="count">Capacity of output area hold XIDs.</param>
        /// <param name="rmid">An integer, assigned by the transaction manager,
        /// uniquely identifies the called resource manager within the thread
        /// of control.</param>
        /// <param name="flags"></param>
        /// <returns>XA_OK for normal execution or an XAER* error code.</returns>
        public int xa_recover(
			out AdvanXID[] xids,
			long count,
			int rmid,
			long flags)
        {
            int rc = XA_OK;

            trace.write(3, "xa_recover: count = " + count.ToString() +
                ", rmid = " + rmid.ToString() +
                ", flags = " + XAFlagsToString(flags));

            xids = new AdvanXID[0];  // init to empty list

            RM rm = FindRM(rmid);
            if (rm == null)  // if RM not found, error
                return XAER_INVAL;

            if ((flags & TMSTARTRSCAN) != 0)  // get a brand new list of XIDs
            {
                rc = xa_recover_startrscan(rm);
                if (rc <= 0)      // return count==0 or error of some kind
                    return rc;
                // else fall through to return sublist
            }

            AdvanXID[] newxids = rm.NextXids(count); // get next, bump up cursor
            if (newxids.Length > 0)  // if some were found, return list
                xids = newxids;

            return xids.Length;
        }
Beispiel #13
0
            /// <summary>
            /// Return the next batch of XIDs in the list.
            /// </summary>
            /// <param name="_count">Max number of XIDs requested.</param>
            /// <returns>An array of AdvanXID containing the XIDs.</returns>
            public AdvanXID[] NextXids(long _count)
            {
                int count = (int)_count;
                int CountRemaining = Xids.Length - Cursor;

                if (count > CountRemaining)
                    count = CountRemaining;

                if (count <= 0)
                    return new AdvanXID[0];

                AdvanXID[] newxids = new AdvanXID[count];
                int i, j;
                for (i = Cursor, j = 0; i < count;)
                    newxids[j++] = Xids[i++];

                Cursor = count;  // bump up the Xid list cursor
                return newxids;
            }
Beispiel #14
0
        /// <summary>
        /// Common code for xa_commit and xa_rollback
        /// </summary>
        /// <param name="isCommit">If commit then true, else rollback.</param>
        /// <param name="xid">XID to perform the work on.</param>
        /// <param name="rmid">An integer, assigned by the transaction manager,
        /// uniquely identifies the called resource manager within the thread
        /// of control.</param>
        /// <param name="flags"></param>
        /// <returns>XA_OK for normal execution or an XAER* error code.</returns>
        private int xa_commit_or_rollback(
			bool     isCommit,
			AdvanXID xid,
			int rmid,
			long flags)
        {
            string title = isCommit?"xa_commit":"xa_rollback";

            RM rm = FindRM(rmid);
            if (rm == null)  // if RM not found, error
                return XAER_INVAL;

            AdvanConnect conn;
            try
            {
                conn =
                    new AdvanConnect(
                        null, rm.Host, rm.Config, trace, xid);
            }
            catch (Exception ex)
            {
                trace.write(title+": Exception thrown on Connection open: "+
                    ex.ToString());
                return XAER_RMERR;  // could not connect
            }

            try
            {
                if (isCommit)
                    conn.commit();
                else
                    conn.rollback();
            }
            catch (Exception ex)
            {
                trace.write(title+": Exception thrown on "+
                    (isCommit?"commit()":"rollback()") + ": " +
                    ex.ToString());
                return XAER_RMERR;  // could not connect
            }

            try
            {
                conn.close();
            }
            catch
            {}

            return XA_OK;
        }
Beispiel #15
0
        /*
        ** Name: AdvanConnect
        **
        ** Description:
        **	Class constructor.  Establish a distributed transaction
        **	management connection.  An XID may be provided, in which
        **	case the server will attempt to assign ownership of the
        **	transaction to the new connection.
        **
        ** Input:
        **	host	Target host and port.
        **	info	Property list.
        **	trace	Connection tracing.
        **	xid	Distributed transaction ID, may be NULL.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	None.
        **
        ** History:
        **	18-Apr-01 (gordy)
        **	    Created.*/
        internal AdvanConnect(IDbConnection providerConnection,
		                   String   host,
		                   IConfig  config,
		                   ITrace   trace,
		                   AdvanXID xid)
            : this(providerConnection, host, trace)
        {
            if (xid != null)
                switch (xid.Type)
                {
                    case AdvanXID.XID_INGRES:
                    case AdvanXID.XID_XA:
                        // OK!
                        break;

                    default:
                        if (trace.enabled(1))
                            trace.write(tr_id + ": unknown XID type: " + xid.Type);
                        throw SqlEx.get( ERR_GC4019_UNSUPPORTED );

                }

            // connect to the Data Access Server
            DrvConn conn = new DrvConn(host, config, trace, true);
            set(conn);  // set the DrvConn into this DrvObj.
            conn.advanConn = this;

            if (conn.msg_protocol_level < MSG_PROTO_2)
            {
                if (trace.enabled(1))
                    trace.write(tr_id + ": 2PC protocol = " + conn.msg_protocol_level);
                conn.close();
                throw SqlEx.get( ERR_GC4019_UNSUPPORTED );
            }

            dbms_connect(config, 0, xid);
        }
Beispiel #16
0
        /*
        ** Name: abortTransaction
        **
        ** Description:
        **	Abort a distributed transaction which is not active on the
        **	current session.  Requires a DTM connection to the server
        **	identified by getTransactionServer() of the session that
        **	is associated with the transaction.
        **
        ** Input:
        **	xid	XA XID.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	void.
        **
        ** History:
        **	10-May-05 (gordy, ported by thoda04 05-Mar-09)
        **	    Created.
        */
        internal void abortTransaction(AdvanXID xid)
        {
            warnings = null;

            if (trace.enabled())
                trace.log(title + ".abortTransaction( '" + xid + "' )");

            if (!conn.is_dtmc)
            {
                if (trace.enabled(1))
                    trace.write(tr_id + ": DTM connection required");
                throw SqlEx.get(ERR_GC4019_UNSUPPORTED);
            }

            if (conn.msg_protocol_level < MSG_PROTO_4)
            {
                if (trace.enabled(1))
                    trace.write(tr_id + ": protocol = " + conn.msg_protocol_level);
                throw SqlEx.get(ERR_GC4019_UNSUPPORTED);
            }

            msg.LockConnection();
            try
            {
                msg.begin(MSG_XACT);
                msg.write(MSG_XACT_ABORT);
                msg.write(MSG_XP_XA_FRMT);
                msg.write((short)4);
                msg.write(xid.FormatId);
                msg.write(MSG_XP_XA_GTID);
                msg.write(xid.getGlobalTransactionId());
                msg.write(MSG_XP_XA_BQUAL);
                msg.write(xid.getBranchQualifier());
                msg.done(true);
                readResults();
            }
            catch (SqlEx ex)
            {
                if (trace.enabled())
                    trace.log(title + ".abortTransaction(): error aborting xact");
                if (trace.enabled(1)) ex.trace(trace);
                throw ex;
            }
            finally
            {
                msg.UnlockConnection();
            }

            return;
        }
Beispiel #17
0
 /*
 ** Name: endTransaction
 **
 ** Description:
 **	End XA transaction association.
 **
 ** Input:
 **	xid	XA XID.
 **
 ** Output:
 **	None.
 **
 ** Returns:
 **	void
 **
 ** History:
 **	20-Jul-06 (gordy)
 **	    Created.
 */
 /// <summary>
 /// End work on behalf of a Distributed Transaction branch.
 /// </summary>
 /// <param name="xid"></param>
 internal void endTransaction(AdvanXID xid)
 {
     endTransaction(xid, 0);
     return;
 }
Beispiel #18
0
        /*
        ** Name: commit
        **
        ** Description:
        **	Commit XA transaction.
        **
        ** Input:
        **	xid	XA XID.
        **	flags	XA Flags.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	void
        **
        ** History:
        **	20-Jul-06 (gordy, ported by thoda04 05-Mar-09)
        **	    Created.
        */
        /// <summary>
        /// Commit work done on behalf of a Distributed Transaction branch.
        /// </summary>
        /// <param name="xid"></param>
        /// <param name="flags"></param>
        internal void commit(AdvanXID xid, int flags)
        {
            if (trace.enabled(2))
                trace.write(tr_id + ".commit( " + xid + ", 0x" +
                     Convert.ToString(flags, 16) + " )");

            warnings = null;

            if (conn.msg_protocol_level < MSG_PROTO_5)
            {
                if (trace.enabled(1)) trace.write(tr_id +
                ".commit: protocol = " + conn.msg_protocol_level);
                throw SqlEx.get(ERR_GC4019_UNSUPPORTED);
            }

            msg.LockConnection();
            try
            {
                msg.begin(MSG_XACT);
                msg.write(MSG_XACT_COMMIT);
                msg.write(MSG_XP_XA_FRMT);
                msg.write((short)4);
                msg.write(xid.FormatId);
                msg.write(MSG_XP_XA_GTID);
                msg.write(xid.getGlobalTransactionId());
                msg.write(MSG_XP_XA_BQUAL);
                msg.write(xid.getBranchQualifier());

                if (flags != 0)
                {
                    msg.write(MSG_XP_XA_FLAGS);
                    msg.write((short)4);
                    msg.write(flags);
                }

                msg.done(true);
                readResults();
            }
            catch (SqlEx sqlEx)
            {
                if (trace.enabled(1))
                {
                    trace.write(tr_id + ".commit: error committing transaction");
                    sqlEx.trace(trace);
                }
                throw sqlEx;
            }
            finally
            {
                msg.UnlockConnection();
            }

            return;
        }
Beispiel #19
0
        /*
        ** Name: rollback
        **
        ** Description:
        **	Rollback XA transaction.
        **
        ** Input:
        **	xid	XA XID.
        **
        ** Output:
        **	None.
        **
        ** Returns:
        **	void
        **
        ** History:
        **	20-Jul-06 (gordy, ported by thoda04 05-Mar-09)
        **	    Created.
        */
        internal void rollback(AdvanXID xid)
        {
            if (trace.enabled(2)) trace.write(tr_id + ".rollback(" + xid + ")");
            warnings = null;

            if (conn.msg_protocol_level < MSG_PROTO_5)
            {
                if (trace.enabled(1)) trace.write(tr_id +
                ".rollback: protocol = " + conn.msg_protocol_level);
                throw SqlEx.get(ERR_GC4019_UNSUPPORTED);
            }

            msg.LockConnection();
            try
            {
                msg.begin(MSG_XACT);
                msg.write(MSG_XACT_ROLLBACK);
                msg.write(MSG_XP_XA_FRMT);
                msg.write((short)4);
                msg.write(xid.FormatId);
                msg.write(MSG_XP_XA_GTID);
                msg.write(xid.getGlobalTransactionId());
                msg.write(MSG_XP_XA_BQUAL);
                msg.write(xid.getBranchQualifier());
                msg.done(true);
                readResults();
            }
            catch (SqlEx sqlEx)
            {
                if (trace.enabled(1))
                {
                    trace.write(tr_id + ".rollback: error rolling back transaction");
                    sqlEx.trace(trace);
                }
                throw sqlEx;
            }
            finally
            {
                msg.UnlockConnection();
            }

            return;
        }