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

org.mariadb.jdbc.MySQLXAResource Maven / Gradle / Ivy

There is a newer version: 8.1.2
Show newest version
package org.mariadb.jdbc;

import org.mariadb.jdbc.internal.mysql.MySQLProtocol;

import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class MySQLXAResource implements XAResource {
    MySQLConnection connection;

    XAException mapXAException(SQLException sqle) {
        int XAErrorCode;

        switch(sqle.getErrorCode()) {
            case 1397:
                XAErrorCode = XAException.XAER_NOTA;
                break;
            case 1398:
                XAErrorCode = XAException.XAER_INVAL;
                break;
            case 1399:
                XAErrorCode = XAException.XAER_RMFAIL;
                break;
            case 1400:
                XAErrorCode = XAException.XAER_OUTSIDE;
                break;
            case 1401:
                XAErrorCode = XAException.XAER_RMERR;
                break;
            case 1402:
                XAErrorCode = XAException.XA_RBROLLBACK;
                break;
            default:
                XAErrorCode = 0;
        }
        if (XAErrorCode != 0)
            return new XAException(XAErrorCode);
        else
            return new XAException(sqle.getMessage());
    }

    void execute(String command) throws XAException {
        //System.out.println(command);
        try {
            connection.createStatement().execute(command);
        }catch (SQLException sqle) {
            throw mapXAException(sqle);
        }
    }


    public MySQLXAResource(MySQLConnection connection) {
        this.connection = connection;
    }

    static String xidToString(Xid xid) {
        StringBuffer sb = new StringBuffer(2*Xid.MAXBQUALSIZE+2*Xid.MAXGTRIDSIZE+16);
        sb.append("0x")
           .append(MySQLProtocol.hexdump(xid.getGlobalTransactionId(),0))
           .append(",0x")
           .append(MySQLProtocol.hexdump(xid.getBranchQualifier(),0))
           .append(",").append(xid.getFormatId());
        return sb.toString();
    }
    public void commit(Xid xid, boolean onePhase) throws XAException {
        String command = "XA COMMIT " + xidToString(xid);
        if (onePhase)
            command += " ONE PHASE";
        execute(command);
    }

    public void end(Xid xid, int flags) throws XAException {
        if (flags != TMSUCCESS && flags != TMSUSPEND && flags != TMFAIL)
            throw new XAException(XAException.XAER_INVAL);

        execute("XA END " + xidToString(xid) + " " + flagsToString(flags));
    }

    public void forget(Xid xid) throws XAException {
       // Not implemented by the server
    }

    public int getTransactionTimeout() throws XAException {
        // not implemented
        return 0;
    }

    public boolean isSameRM(XAResource xaResource) throws XAException {
        // Typically used by transaction manager to "join" transactions. We do not support joins,
        // so always return false;
        return false;
    }

    public int prepare(Xid xid) throws XAException {
        execute("XA PREPARE " +xidToString(xid));
        return XA_OK;
    }

    public Xid[] recover(int flags) throws XAException {
        // Return all Xid  at once, when STARTRSCAN is specified
        // Return zero-length array otherwise.

        if ( ((flags & TMSTARTRSCAN) == 0) && ((flags & TMENDRSCAN) == 0) && (flags != TMNOFLAGS))
            throw new XAException(XAException.XAER_INVAL);

        if ((flags & TMSTARTRSCAN) == 0)
            return new MySQLXid[0];

        try {
            ResultSet rs = connection.createStatement().executeQuery("XA RECOVER");
            ArrayList xidList= new ArrayList();

            while(rs.next()) {
                int formatId = rs.getInt(1);
                int len1 = rs.getInt(2);
                int len2 = rs.getInt(3);
                byte[] arr = rs.getBytes(4);

                byte[] globalTransactionId = new byte[len1];
                byte[] branchQualifier = new byte[len2];
                System.arraycopy(arr, 0, globalTransactionId, 0, len1);
                System.arraycopy(arr, len1, branchQualifier, 0, len2);
                xidList.add(new MySQLXid(formatId,globalTransactionId, branchQualifier));
            }
            Xid[] xids = new Xid[xidList.size()];
            xidList.toArray(xids);
            return xids;
        }catch (SQLException sqle) {
           throw mapXAException(sqle);
        }
    }

    public void rollback(Xid xid) throws XAException {
       execute("XA ROLLBACK " + xidToString(xid));
    }

    public boolean setTransactionTimeout(int timeout) throws XAException {
        return false; // not implemented
    }

    public void start(Xid xid, int flags) throws XAException {
        if (flags != TMJOIN && flags != TMRESUME && flags != TMNOFLAGS)
            throw new XAException(XAException.XAER_INVAL);
        if (flags == TMJOIN && connection.getPinGlobalTxToPhysicalConnection()) {
        	flags = TMRESUME;
        }
        execute("XA START " + xidToString(xid) + " "+flagsToString(flags));
    }

    static String flagsToString(int flags) {
       switch(flags) {
           case TMJOIN:
               return "JOIN";
           case TMONEPHASE:
               return "ONE PHASE";
           case TMRESUME:
               return "RESUME";
           case TMSUSPEND:
               return "SUSPEND";
           default:
               return "";
       }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy