com.swiftmq.jms.v750.XAResourceImpl Maven / Gradle / Ivy
/*
* Copyright 2019 IIT Software GmbH
*
* IIT Software GmbH licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.swiftmq.jms.v750;
import com.swiftmq.jms.XACompletionListener;
import com.swiftmq.jms.XAResourceExtended;
import com.swiftmq.jms.XidImpl;
import com.swiftmq.jms.smqp.v750.*;
import com.swiftmq.tools.requestreply.Request;
import com.swiftmq.tools.requestreply.RequestRetryValidator;
import com.swiftmq.tools.requestreply.ValidationException;
import javax.jms.JMSException;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class XAResourceImpl implements XAResourceExtended, RequestRetryValidator {
private static final SimpleDateFormat format = new SimpleDateFormat("yyMMdd:HH:mm:ss.SSS");
XASessionImpl session = null;
Map xidMapping = new HashMap();
XACompletionListener completionListener = null;
int nRecoverCalls = 0;
// PrintWriter logWriter = new PrintWriter(new OutputStreamWriter(System.out));
PrintWriter logWriter = null;
int lastEndRequestConnectionId = -1;
boolean neverSameRM = false;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
XAResourceImpl(XASessionImpl session) {
this.session = session;
session.getSessionImpl().setAutoAssign(false);
session.getSessionImpl().setXaMode(true);
}
public void setNeverSameRM(boolean neverSameRM) {
this.neverSameRM = neverSameRM;
if (logWriter != null) log(toString() + "/setNeverSameRM, neverSameRM=" + neverSameRM);
}
private boolean endRequestInDoubt() {
boolean rc = false;
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
if (lastEndRequestConnectionId == -1 || connectionId == -1)
rc = false;
else
rc = lastEndRequestConnectionId < connectionId;
if (logWriter != null)
log(toString() + "/endRequestInDoubt, rc=" + rc + ", lastEndRequestConnectionId" + lastEndRequestConnectionId + ", connectionId=" + connectionId);
return rc;
}
public void validate(Request request) throws ValidationException {
if (logWriter != null) log(toString() + "/validate, request=" + request + " ...");
request.setDispatchId(session.getDispatchId());
request.setConnectionId(session.getSessionImpl().getMyConnection().getConnectionId());
if (request instanceof XAResStartRequest) {
XAResStartRequest r = (XAResStartRequest) request;
r.setRetry(true);
List l = XARecoverRegistry.getInstance().getRequestList(r.getXid());
r.setRecoverRequestList(l);
} else if (request instanceof XAResEndRequest) {
XAResEndRequest r = (XAResEndRequest) request;
r.setRetry(true);
List l = XARecoverRegistry.getInstance().getRequestList(r.getXid());
r.setRecoverRequestList(l);
} else if (request instanceof XAResPrepareRequest) {
XAResPrepareRequest r = (XAResPrepareRequest) request;
r.setRetry(true);
List l = XARecoverRegistry.getInstance().getRequestList(r.getXid());
r.setRecoverRequestList(l);
} else if (request instanceof XAResCommitRequest) {
XAResCommitRequest r = (XAResCommitRequest) request;
r.setRetry(true);
List l = XARecoverRegistry.getInstance().getRequestList(r.getXid());
r.setRecoverRequestList(l);
} else if (request instanceof XAResRollbackRequest) {
XAResRollbackRequest r = (XAResRollbackRequest) request;
r.setRetry(true);
List l = XARecoverRegistry.getInstance().getRequestList(r.getXid());
r.setRecoverRequestList(l);
} else if (request instanceof XAResForgetRequest) {
XAResForgetRequest r = (XAResForgetRequest) request;
r.setRetry(true);
}
if (logWriter != null) log(toString() + "/validate, request=" + request + " done");
}
private XidImpl toSwiftMQXid(Xid xid) {
XidImpl rXid = null;
if (xid instanceof com.swiftmq.jms.XidImpl)
rXid = (XidImpl) xid;
else {
rXid = (XidImpl) xidMapping.get(xid);
if (rXid == null) {
rXid = new XidImpl(xid);
xidMapping.put(xid, rXid);
}
}
if (logWriter != null) log(toString() + "/toSwiftMQXid, xid=" + xid + ", rXid=" + rXid);
return rXid;
}
private Xid[] toArray(List xidList) {
if (logWriter != null) log(toString() + "/toArray, xidList=" + xidList);
if (xidList == null || xidList.size() == 0)
return new Xid[0];
Xid[] xids = new Xid[xidList.size()];
for (int i = 0; i < xidList.size(); i++) {
xids[i] = (Xid) xidList.get(i);
}
return xids;
}
private boolean isFlagSet(int flags, int flag) {
return (flags & flag) == flag;
}
public PrintWriter getLogWriter() {
return logWriter;
}
public void setLogWriter(PrintWriter logWriter) {
this.logWriter = logWriter;
}
protected void log(String msg) {
try {
logWriter.println(format.format(new Date()) + "/" + msg);
logWriter.flush();
} catch (Exception e) {
}
}
public void setCompletionListener(XACompletionListener completionListener) {
lock.writeLock().lock();
try {
this.completionListener = completionListener;
} finally {
lock.writeLock().unlock();
}
}
public String getRouterName() {
return session.getSessionImpl().myConnection.metaData.getRouterName();
}
public boolean setTransactionTimeout(int seconds) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/setTransactionTimeout, seconds=" + seconds);
XAResSetTxTimeoutReply reply = null;
try {
reply = (XAResSetTxTimeoutReply) session.request(new XAResSetTxTimeoutRequest(this, session.getDispatchId(), (long) (seconds * 1000)));
if (!reply.isOk())
throw reply.getException();
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
return true;
} finally {
lock.writeLock().unlock();
}
}
public int getTransactionTimeout() throws XAException {
lock.readLock().lock();
try {
XAResGetTxTimeoutReply reply = null;
try {
reply = (XAResGetTxTimeoutReply) session.request(new XAResGetTxTimeoutRequest(this, session.getDispatchId()));
if (!reply.isOk())
throw reply.getException();
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
int secs = (int) (reply.getTxTimeout() / 1000);
if (logWriter != null) log(toString() + "/getTransactionTimeout, secs=" + secs);
return secs;
} finally {
lock.readLock().unlock();
}
}
public boolean isSameRM(XAResource resource) throws XAException {
if (logWriter != null) log(toString() + "/isSameRM, neverSameRM=" + neverSameRM);
if (neverSameRM)
return false;
boolean b = false;
if (resource instanceof XAResourceExtended) {
XAResourceExtended that = (XAResourceExtended) resource;
b = that.getRouterName().equals(getRouterName());
}
if (logWriter != null) log(toString() + "/isSameRM, resource=" + resource + ", returns=" + b);
return b;
}
public Xid[] recover(int flag) throws XAException {
lock.writeLock().lock();
try {
if (isFlagSet(flag, XAResource.TMSTARTRSCAN)) {
if (logWriter != null)
log(toString() + "/TMSTARTRSCAN, flag=" + flag + ", nRecoverCalls=" + nRecoverCalls);
nRecoverCalls = 0;
} else if (logWriter != null)
log(toString() + "/TMONOFLAGS, flag=" + flag + ", nRecoverCalls=" + nRecoverCalls);
if (nRecoverCalls > 0)
return new Xid[0];
nRecoverCalls++;
XAResRecoverReply reply = null;
try {
reply = (XAResRecoverReply) session.request(new XAResRecoverRequest(this, session.getDispatchId(), flag));
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (reply.isOk())
return toArray(reply.getXids());
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
} finally {
lock.writeLock().unlock();
}
}
public void start(Xid xid, int flags) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/start, xid=" + xid + ", flags=" + flags);
XidImpl sxid = toSwiftMQXid(xid);
XAResStartReply reply = null;
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
Request request = new XAResStartRequest(this, session.getDispatchId(), sxid, flags, false, null);
request.setConnectionId(connectionId);
try {
reply = (XAResStartReply) session.request(request);
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (!reply.isOk()) {
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
} else {
XARecoverRegistry.getInstance().addRequest(sxid, request);
try {
session.session.assignLastMessage();
} catch (Exception e) {
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
}
if (completionListener != null)
completionListener.transactionStarted(sxid, session);
} finally {
lock.writeLock().unlock();
}
}
public void end(Xid xid, int flags) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/end, xid=" + xid + ", flags=" + flags);
XidImpl sxid = toSwiftMQXid(xid);
XAResEndReply reply = null;
XAResEndRequest request = null;
try {
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
List content = session.getAndClearCurrentTransaction();
if (content != null && content.size() == 0)
content = null;
request = new XAResEndRequest(this, session.getDispatchId(), sxid, flags, false, content, XARecoverRegistry.getInstance().getRequestList(sxid));
request.setConnectionId(connectionId);
lastEndRequestConnectionId = connectionId;
reply = (XAResEndReply) session.request(request);
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (!reply.isOk()) {
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
request.setRecoverRequestList(null);
XARecoverRegistry.getInstance().addRequest(sxid, request);
if (completionListener != null)
completionListener.transactionEnded(sxid);
} finally {
lock.writeLock().unlock();
}
}
public void forget(Xid xid) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/forget, xid=" + xid);
XidImpl sxid = toSwiftMQXid(xid);
xidMapping.remove(xid);
XAResForgetReply reply = null;
try {
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
Request request = new XAResForgetRequest(this, session.getDispatchId(), sxid, false);
request.setConnectionId(connectionId);
reply = (XAResForgetReply) session.request(request);
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (!reply.isOk()) {
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
} finally {
lock.writeLock().unlock();
}
}
public int prepare(Xid xid) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/prepare, xid=" + xid);
XidImpl sxid = toSwiftMQXid(xid);
XAResPrepareReply reply = null;
try {
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
Request request = new XAResPrepareRequest(this, session.getDispatchId(), sxid, false, endRequestInDoubt() ? XARecoverRegistry.getInstance().getRequestList(sxid) : null);
request.setConnectionId(connectionId);
reply = (XAResPrepareReply) session.request(request);
} catch (Exception e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (!reply.isOk()) {
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
XARecoverRegistry.getInstance().clear(sxid);
return XA_OK;
} finally {
lock.writeLock().unlock();
}
}
public void commit(Xid xid, boolean onePhase) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/commit, xid=" + xid + ", onePhase=" + onePhase);
XidImpl sxid = toSwiftMQXid(xid);
xidMapping.remove(xid);
XAResCommitReply reply = null;
try {
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
XAResCommitRequest req = new XAResCommitRequest(this, session.getDispatchId(), sxid, onePhase, false, onePhase && endRequestInDoubt() ? XARecoverRegistry.getInstance().getRequestList(sxid) : null);
req.setConnectionId(connectionId);
reply = (XAResCommitReply) session.request(req);
} catch (Exception e) {
if (completionListener != null)
completionListener.transactionCommitted(sxid);
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (!reply.isOk()) {
if (completionListener != null)
completionListener.transactionCommitted(sxid);
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
} else {
try {
session.getSessionImpl().afterCommit();
} catch (JMSException e) {
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (reply.getDelay() > 0) {
try {
Thread.sleep(reply.getDelay());
} catch (Exception ignored) {
}
}
if (completionListener != null)
completionListener.transactionCommitted(sxid);
XARecoverRegistry.getInstance().clear(sxid);
}
} finally {
lock.writeLock().unlock();
}
}
public void rollback(Xid xid) throws XAException {
lock.writeLock().lock();
try {
if (logWriter != null) log(toString() + "/rollback, xid=" + xid);
XidImpl sxid = toSwiftMQXid(xid);
xidMapping.remove(xid);
XAResRollbackReply reply = null;
try {
int connectionId = session.getSessionImpl().getMyConnection().getConnectionId();
session.getSessionImpl().startRecoverConsumers();
session.getAndClearCurrentTransaction();
List recoveryList = null;
if (endRequestInDoubt())
recoveryList = XARecoverRegistry.getInstance().getRequestList(sxid);
Request request = new XAResRollbackRequest(this, session.getDispatchId(), sxid, false, recoveryList, session.getSessionImpl().getRecoveryEpoche());
request.setConnectionId(connectionId);
reply = (XAResRollbackReply) session.request(request);
} catch (Exception e) {
if (completionListener != null)
completionListener.transactionAborted(sxid);
XAException ex = new XAException(e.toString());
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
if (reply.isOk()) {
session.getSessionImpl().endRecoverConsumersXA();
try {
session.getSessionImpl().closeDelayedProducers();
} catch (JMSException e) {
e.printStackTrace();
}
if (completionListener != null)
completionListener.transactionAborted(sxid);
XARecoverRegistry.getInstance().clear(sxid);
} else {
if (completionListener != null)
completionListener.transactionAborted(sxid);
XAException ex = new XAException(reply.getException().getMessage());
if (reply.getErrorCode() != 0)
ex.errorCode = reply.getErrorCode();
else
ex.errorCode = XAException.XAER_RMFAIL;
throw ex;
}
} finally {
lock.writeLock().unlock();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy