/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and/or its affiliates,
* and individual contributors as indicated by the @author tags.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2011,
* @author JBoss, by Red Hat.
*/
package com.arjuna.ats.internal.jbossatx.jta;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.transaction.xa.XAResource;
import org.jboss.tm.XAResourceWrapper;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.coordinator.TxControl;
import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
import com.arjuna.ats.arjuna.objectstore.ObjectStoreAPI;
import com.arjuna.ats.arjuna.objectstore.StoreManager;
import com.arjuna.ats.arjuna.state.InputObjectState;
import com.arjuna.ats.arjuna.state.OutputObjectState;
import com.arjuna.ats.internal.arjuna.common.UidHelper;
import com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord;
import com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecordWrappingPlugin;
/**
* A plugin implementation for copying resource metadata from the JBoss AS
* specific XAResourceWrapper class to an XAResourceRecord.
*
* @author Jonathan Halliday (jonathan.halliday@redhat.com) 2011-07
*/
public class XAResourceRecordWrappingPluginImpl implements XAResourceRecordWrappingPlugin {
private ConcurrentMap<Integer, String> keyToName = new ConcurrentHashMap<Integer, String>();
private ConcurrentMap<String, Integer> nameToKey = new ConcurrentHashMap<String, Integer>();
private AtomicInteger nextKey = new AtomicInteger(1);
private ObjectStoreAPI eisNameStore;
private String nodeIdentifier;
public void transcribeWrapperData(XAResourceRecord record) {
XAResource xaResource = (XAResource) record.value();
if (xaResource instanceof XAResourceWrapper) {
XAResourceWrapper xaResourceWrapper = (XAResourceWrapper) xaResource;
record.setProductName(xaResourceWrapper.getProductName());
record.setProductVersion(xaResourceWrapper.getProductVersion());
record.setJndiName(xaResourceWrapper.getJndiName());
}
}
public Integer getEISName(XAResource xaResource) throws IOException, ObjectStoreException {
if (xaResource instanceof XAResourceWrapper) {
initialize();
String jndiName = ((XAResourceWrapper) xaResource).getJndiName();
Integer key = nameToKey.get(jndiName);
if (key == null) {
synchronized (this) {
// Recheck the resource, we do this so that we don't need to
// synchronize if this is a read
key = nameToKey.get(jndiName);
if (key == null) {
key = nextKey.getAndIncrement();
keyToName.put(key, jndiName);
nameToKey.put(jndiName, key);
OutputObjectState oos = new OutputObjectState();
oos.packString(nodeIdentifier);
oos.packInt(key);
oos.packString(jndiName);
eisNameStore.write_committed(new Uid(), "EISNAME", oos);
eisNameStore.sync();
}
}
}
return key;
} else {
return 0;
}
}
@Override
public String getEISName(Integer eisKey) {
try {
initialize();
} catch (IOException ioe) {
return "unloadable EIS key file: " + eisKey;
} catch (ObjectStoreException e) {
return "unloadable EIS key file: " + eisKey;
}
if (eisKey == 0) {
return "unknown eis name";
} else if (eisKey == -1) {
return "foreign XID";
} else {
String eisName = keyToName.get(eisKey);
if (eisName == null) {
return "forgot eis name for: " + eisKey;
} else {
return eisName;
}
}
}
private void initialize() throws ObjectStoreException, IOException {
if (this.nodeIdentifier == null) {
synchronized (this) {
// If we are here, check again that the node idenfier is still
// null in case of race condition
if (this.nodeIdentifier == null) {
this.nodeIdentifier = TxControl.getXANodeName();
this.eisNameStore = StoreManager.getEISNameStore();
InputObjectState states = new InputObjectState();
int keyMax = 0;
boolean allObjUids = eisNameStore.allObjUids("EISNAME", states);
while (states.notempty()) {
Uid uid = UidHelper.unpackFrom(states);
if (uid.equals(Uid.nullUid())) {
break;
} else {
InputObjectState oState = eisNameStore.read_committed(uid, "EISNAME");
String nodeName = oState.unpackString();
if (nodeName.equals(nodeIdentifier)) {
Integer key = oState.unpackInt();
String jndiName = oState.unpackString();
keyToName.put(key, jndiName);
nameToKey.put(jndiName, key);
if (key > keyMax) {
keyMax = key;
}
} else {
// logger warn that we are using a new node
}
}
}
nextKey.set(keyMax + 1);
}
}
}
}
}