package com.bagri.client.hazelcast.impl;
import static com.bagri.core.server.api.CacheConstants.PN_XDM_SCHEMA_POOL;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.bagri.client.hazelcast.task.tx.TransactionAborter;
import com.bagri.client.hazelcast.task.tx.TransactionCommiter;
import com.bagri.client.hazelcast.task.tx.TransactionStarter;
import com.bagri.core.api.TransactionIsolation;
import com.bagri.core.api.TransactionManagement;
import com.bagri.core.api.BagriException;
import com.hazelcast.core.HazelcastInstance;
import com.hazelcast.core.IExecutorService;
public class TransactionManagementImpl implements TransactionManagement {
private static final Logger logger = LoggerFactory.getLogger(TransactionManagementImpl.class);
private long txId = TX_NO;
private long txTimeout = 0;
private String clientId = null;
private SchemaRepositoryImpl repo;
private IExecutorService execService;
void initialize(SchemaRepositoryImpl repo) {
this.repo = repo;
HazelcastInstance hzClient = repo.getHazelcastClient();
execService = hzClient.getExecutorService(PN_XDM_SCHEMA_POOL);
clientId = repo.getClientId();
}
public long getTransactionTimeout() {
return txTimeout;
}
public void setTransactionTimeout(long timeout) throws BagriException {
if (timeout < 0) {
throw new BagriException("negative timeout value is not supported", BagriException.ecTransaction);
}
this.txTimeout = timeout;
}
@Override
public boolean isInTransaction() {
return txId > TX_NO;
}
@Override
public long beginTransaction() throws BagriException {
// TODO: get default value from session config!
return beginTransaction(TransactionIsolation.readCommited);
}
@Override
public long beginTransaction(TransactionIsolation txIsolation) throws BagriException {
logger.trace("beginTransaction.enter; current txId: {}", txId);
repo.getHealthManagement().checkClusterState();
if (txId != TX_NO) {
throw new BagriException("Nested client transactions are not supported", BagriException.ecTransNoNested);
}
TransactionStarter txs = new TransactionStarter(clientId, txIsolation);
Future<Long> future = execService.submitToKeyOwner(txs, clientId);
try {
txId = future.get();
} catch (InterruptedException | ExecutionException ex) {
logger.error("beginTransaction; error getting result", ex);
throw new BagriException(ex, BagriException.ecTransaction);
}
logger.trace("beginTransaction.exit; returnig txId: {}", txId);
return txId;
}
@Override
public void commitTransaction(long txId) throws BagriException {
logger.trace("commitTransaction.enter; current txId: {}", this.txId);
if (this.txId != txId) {
throw new BagriException("Wrong transaction id: " + txId + "; current txId is: " + this.txId,
BagriException.ecTransWrongState);
}
boolean result = false;
TransactionCommiter txc = new TransactionCommiter(clientId, this.txId);
Future<Boolean> future = execService.submitToKeyOwner(txc, clientId);
try {
result = future.get();
this.txId = TX_NO;
} catch (InterruptedException | ExecutionException ex) {
this.txId = TX_NO;
logger.error("commitTransaction; error getting result", ex);
throw new BagriException(ex, BagriException.ecTransaction);
}
logger.trace("commitTransaction.exit; commited: {}", result);
}
@Override
public void rollbackTransaction(long txId) throws BagriException {
logger.trace("rollbackTransaction.enter; current txId: {}", this.txId);
if (this.txId != txId) {
throw new BagriException("Wrong transaction id: " + txId + "; current txId is: " + this.txId,
BagriException.ecTransWrongState);
}
boolean result = false;
TransactionAborter txa = new TransactionAborter(clientId, this.txId);
Future<Boolean> future = execService.submitToKeyOwner(txa, clientId);
try {
result = future.get();
this.txId = TX_NO;
} catch (InterruptedException | ExecutionException ex) {
this.txId = TX_NO;
logger.error("rollbackTransaction; error getting result", ex);
throw new BagriException(ex, BagriException.ecTransaction);
}
logger.trace("rollbackTransaction.exit; rolled back: {}", result);
}
@Override
public boolean finishCurrentTransaction(boolean rollback) throws BagriException {
if (isInTransaction()) {
if (rollback) {
rollbackTransaction(txId);
} else {
commitTransaction(txId);
}
return true;
}
return false;
}
long getTxId() {
return this.txId;
}
}