package org.radargun.service;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.tangosol.coherence.transaction.Connection;
import com.tangosol.coherence.transaction.ConnectionFactory;
import com.tangosol.coherence.transaction.DefaultConnectionFactory;
import com.tangosol.net.NamedCache;
import org.radargun.traits.Transactional;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
public class CoherenceTransactional implements Transactional {
protected final Coherence3Service service;
protected volatile ConnectionFactory connectionFactory;
public CoherenceTransactional(Coherence3Service service) {
this.service = service;
}
@Override
public Configuration getConfiguration(String cacheName) {
return Configuration.TRANSACTIONS_ENABLED;
}
@Override
public Transaction getTransaction() {
ensureConnectionFactory();
return new ConnectionTx();
}
private void ensureConnectionFactory() {
if (connectionFactory == null) {
synchronized (this) {
if (connectionFactory == null) {
if (service.connectionFactory == null) {
connectionFactory = new DefaultConnectionFactory();
} else {
try {
connectionFactory = InitialContext.doLookup(service.connectionFactory);
} catch (NamingException e) {
throw new IllegalArgumentException("Failed to lookup connection factory", e);
}
}
}
}
}
}
protected class ConnectionTx implements Transaction {
private Connection connection;
public ConnectionTx() {
}
@Override
public <T> T wrap(T resource) {
if (resource == null) {
return null;
} else if (connection == null) {
throw new IllegalStateException("Transaction had not begun yet");
} else if (resource instanceof NamedCache) {
String cacheName = ((NamedCache) resource).getCacheName();
return (T) connection.getNamedCache(cacheName);
} else if (resource instanceof CoherenceOperations.Cache) {
String cacheName = ((CoherenceOperations.Cache) resource).cache.getCacheName();
return (T) new CoherenceOperations.Cache(connection.getNamedCache(cacheName));
} else if (resource instanceof CoherenceQueryable.QueryContextImpl) {
String cacheName = ((CoherenceQueryable.QueryContextImpl) resource).cache.getCacheName();
return (T) new CoherenceQueryable.QueryContextImpl(connection.getNamedCache(cacheName));
} else {
throw new IllegalArgumentException(String.valueOf(resource));
}
}
@Override
public void begin() {
if (service.transactionalService == null) {
this.connection = connectionFactory.createConnection();
} else {
connection = connectionFactory.createConnection(service.transactionalService);
}
connection.setAutoCommit(false);
}
@Override
public void commit() {
endTransaction(true);
}
@Override
public void rollback() {
endTransaction(false);
}
private void endTransaction(boolean successful) {
if (connection == null) {
throw new IllegalStateException("Transaction was not started");
}
try {
if (successful) connection.commit();
else connection.rollback();
} finally {
connection.close();
}
}
}
}