com.sun.xml.ws.tx.at.internal.BranchRecord Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of webservices-osgi Show documentation
Show all versions of webservices-osgi Show documentation
Metro Web Services Runtime OSGi Bundle
The newest version!
/*
* Copyright (c) 1997, 2022 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
package com.sun.xml.ws.tx.at.internal;
import com.sun.istack.logging.Logger;
import com.sun.xml.ws.tx.at.WSATHelper;
import com.sun.xml.ws.tx.at.WSATXAResource;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
/**
* Encapsulates remote WS-AT participants as a branch for this superior
* transaction.
*/
public class BranchRecord implements Externalizable {
private static final long serialVersionUID = -8663994789749988958L;
private static final int VERSION = 1;
private Xid globalXid;
private Map registeredResources;
private String branchAliasSuffix = "BI_WSATGatewayRM"; //this should be different from the WSATGateway resource name prefix, and should keep it short.
private boolean logged;
private String txLogLocation;
private static final Logger LOGGER = Logger.getLogger(BranchRecord.class);
/**
* Used for recovery (created by readObject) and Externalizable no-arg constructor
*/
public BranchRecord() {
this.registeredResources = new HashMap<>();
}
BranchRecord(Xid xid) {
this.globalXid = xid;
this.registeredResources = new HashMap<>();
}
/**
* Adds the specified WS-AT resource to the gateway branch record.
* @param xid Xid used for key
* @param wsatResource WSATXAResource
* @return RegisteredResource that contains (WSAT)XAResource provided
*/
public synchronized RegisteredResource addSubordinate(Xid xid, WSATXAResource wsatResource) {
debug("addSubordindate xid:"+xid+" wsatResource:"+wsatResource);
RegisteredResource rr = new RegisteredResource(wsatResource);
registeredResources.put(xid, rr);
return rr;
}
/**
* Returns the transaction branch name of the specified WS-AT resource in order to enlist the resource.
* Each call will return a different value for the same wsatResource and
* so it should only be called once for each resource.
* @param wsatResource WSATXAResource
* @return String representing
*/
synchronized String getBranchName(XAResource wsatResource) {
int index = getResourceIndex(wsatResource);
if (index == -1) {
throw new IllegalStateException(
"WS-AT resource not associated with transaction branch " + globalXid);
}
return index + branchAliasSuffix;
}
/**
* If persist of record was successfully logged
* @param b boolean
*/
void setLogged(boolean b) {
this.logged = b;
}
/**
* If persist of record was successfully logged
* @return boolean
*/
boolean isLogged() {
return logged;
}
int prepare(Xid xid) throws XAException {
/*
if (isPrimaryBranch(xid)) {
// primary branch always returns RDONLY
debug("prepare() xid=" + xid + " returning XA_RDONLY");
return XAResource.XA_RDONLY;
}
*/
RegisteredResource rr = getRegisteredResource(xid);
int vote = XAResource.XA_OK;
try {
vote = rr.prepare(xid);
} catch (XAException xae) {
switch(xae.errorCode) {
case XAException.XA_RBROLLBACK:
// throw rollback, TM will call rollback
throw xae;
// case XAException.XA_HEURMIX:
// case XAException.XA_HEURHAZ:
// heuristic = true;
// break;
case XAException.XAER_NOTA:
// possible timeout of subordinate, initiate rollback
JTAHelper.throwXAException(XAException.XA_RBTIMEOUT, "Subordinate resource timeout.", xae);
break;
default:
throw xae;
}
}
return vote;
}
void rollback(Xid xid) throws XAException {
if (isPrimaryBranch(xid)) {
debug("rollback() xid=" + xid + " ignoring primary branch ");
}
RegisteredResource rr = getRegisteredResource(xid);
try {
rr.rollback(xid);
} catch (XAException e) {
switch (e.errorCode) {
case XAException.XA_HEURMIX:
case XAException.XA_HEURHAZ:
case XAException.XA_HEURCOM:
throw e;
case XAException.XAER_NOTA:
// ignore, assume completion
break;
default:
throw e;
}
}
}
void commit(Xid xid, boolean onePhase) throws XAException {
if (isPrimaryBranch(xid)) {
debug("commit() xid=" + xid + " ignoring primary branch");
//This happens in superior during migration recovery and so should not do a
// JTAHelper.throwXAException(XAException.XAER_NOTA, "Primary branch RDONLY");
}
RegisteredResource rr = getRegisteredResource(xid);
try {
rr.commit(xid, onePhase);
} catch (XAException e) {
switch (e.errorCode) {
case XAException.XA_HEURMIX:
case XAException.XA_HEURHAZ:
case XAException.XA_HEURRB:
throw e;
case XAException.XAER_NOTA:
// ignore, assume completion
break;
default:
throw e;
}
}
}
/**
* Returns the branch index of the specified WS-AT resource
*
* @param wsatResource WSATXAResource
* @return the branch index, or -1 if DNE.
*/
private synchronized int getResourceIndex(XAResource wsatResource) {
for (int i=0; i getAllXids() {
Collection xids = new ArrayList<>();
Iterator resourceIterator = registeredResources.values().iterator();
while(resourceIterator.hasNext()) {
xids.add(resourceIterator.next().getBranchXid());
}
return xids;
}
// ensure that each registered resource has an associated Xid w/ bqual
void assignBranchXid(Xid xid) {
int index = getResourceIndex(xid);
if (index == -1) return;
RegisteredResource rr = registeredResources.get(index);
if (rr == null) return;
if (rr.getBranchXid() == null) rr.setBranchXid(xid);
}
public void cleanup() {
// perform any necessary branch record cleanup, release resource, etc.
// on WS-AT participant XAResource
}
synchronized boolean allResourcesCompleted() {
for (int i=0, num=registeredResources.size(); i resourceIterator = registeredResources.values().iterator();
while(resourceIterator.hasNext()) {
resourceIterator.next().writeExternal(out);
}
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
// Version
int version = in.readInt();
if (version != VERSION) {
throw new IOException("invalid OTSBranch version " + version);
}
// Global Xid
int formatId = in.readInt();
int len = in.readByte();
byte[] gtrid = new byte[len];
in.readFully(gtrid);
len = in.readByte();
byte[] bqual=null;
if (len > -1) {
bqual = new byte[len];
in.readFully(bqual);
}
// globalXid = XIDFactory.createXID(formatId, gtrid, bqual);
globalXid = new XidImpl(formatId, gtrid, bqual);
// RegisteredResources
int resourceNum = in.readInt();
for (int i=0; i