use of org.apache.geode.internal.cache.TXSynchronizationRunnable in project geode by apache.
the class TXSynchronizationCommand method cmdExecute.
/*
* (non-Javadoc)
*
* @see
* org.apache.geode.internal.cache.tier.sockets.BaseCommand#cmdExecute(org.apache.geode.internal.
* cache.tier.sockets.Message, org.apache.geode.internal.cache.tier.sockets.ServerConnection,
* long)
*/
@Override
public void cmdExecute(final Message clientMessage, final ServerConnection serverConnection, long start) throws IOException, ClassNotFoundException, InterruptedException {
serverConnection.setAsTrue(REQUIRES_RESPONSE);
CompletionType type = CompletionType.values()[clientMessage.getPart(0).getInt()];
/* int txIdInt = */
// [bruce] not sure if we need to
clientMessage.getPart(1).getInt();
// transmit this
final Part statusPart;
if (type == CompletionType.AFTER_COMPLETION) {
statusPart = clientMessage.getPart(2);
} else {
statusPart = null;
}
final TXManagerImpl txMgr = (TXManagerImpl) serverConnection.getCache().getCacheTransactionManager();
final InternalDistributedMember member = (InternalDistributedMember) serverConnection.getProxyID().getDistributedMember();
// get the tx state without associating it with this thread. That's done later
final TXStateProxy txProxy = txMgr.masqueradeAs(clientMessage, member, true);
// releases them
if (txProxy != null) {
final boolean isDebugEnabled = logger.isDebugEnabled();
try {
if (type == CompletionType.BEFORE_COMPLETION) {
Runnable beforeCompletion = new Runnable() {
@SuppressWarnings("synthetic-access")
public void run() {
TXStateProxy txState = null;
Throwable failureException = null;
try {
txState = txMgr.masqueradeAs(clientMessage, member, false);
if (isDebugEnabled) {
logger.debug("Executing beforeCompletion() notification for transaction {}", clientMessage.getTransactionId());
}
txState.setIsJTA(true);
txState.beforeCompletion();
try {
writeReply(clientMessage, serverConnection);
} catch (IOException e) {
if (isDebugEnabled) {
logger.debug("Problem writing reply to client", e);
}
}
serverConnection.setAsTrue(RESPONDED);
} catch (ReplyException e) {
failureException = e.getCause();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
failureException = e;
} finally {
txMgr.unmasquerade(txState);
}
if (failureException != null) {
try {
writeException(clientMessage, failureException, false, serverConnection);
} catch (IOException ioe) {
if (isDebugEnabled) {
logger.debug("Problem writing reply to client", ioe);
}
}
serverConnection.setAsTrue(RESPONDED);
}
}
};
TXSynchronizationRunnable sync = new TXSynchronizationRunnable(beforeCompletion);
txProxy.setSynchronizationRunnable(sync);
Executor exec = InternalDistributedSystem.getConnectedInstance().getDistributionManager().getWaitingThreadPool();
exec.execute(sync);
sync.waitForFirstExecution();
} else {
Runnable afterCompletion = new Runnable() {
@SuppressWarnings("synthetic-access")
public void run() {
TXStateProxy txState = null;
try {
txState = txMgr.masqueradeAs(clientMessage, member, false);
int status = statusPart.getInt();
if (isDebugEnabled) {
logger.debug("Executing afterCompletion({}) notification for transaction {}", status, clientMessage.getTransactionId());
}
txState.setIsJTA(true);
txState.afterCompletion(status);
// GemFire commits during afterCompletion - send the commit info back to the client
// where it can be applied to the local cache
TXCommitMessage cmsg = txState.getCommitMessage();
try {
CommitCommand.writeCommitResponse(cmsg, clientMessage, serverConnection);
txMgr.removeHostedTXState(txState.getTxId());
} catch (IOException e) {
// not much can be done here
if (isDebugEnabled || (e instanceof MessageTooLargeException)) {
logger.warn("Problem writing reply to client", e);
}
}
serverConnection.setAsTrue(RESPONDED);
} catch (RuntimeException e) {
try {
writeException(clientMessage, e, false, serverConnection);
} catch (IOException ioe) {
if (isDebugEnabled) {
logger.debug("Problem writing reply to client", ioe);
}
}
serverConnection.setAsTrue(RESPONDED);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
txMgr.unmasquerade(txState);
}
}
};
// if there was a beforeCompletion call then there will be a thread
// sitting in the waiting pool to execute afterCompletion. Otherwise
// we have failed-over and may need to do beforeCompletion & hope that it works
TXSynchronizationRunnable sync = txProxy.getSynchronizationRunnable();
if (sync != null) {
sync.runSecondRunnable(afterCompletion);
} else {
if (statusPart.getInt() == Status.STATUS_COMMITTED) {
TXStateProxy txState = txMgr.masqueradeAs(clientMessage, member, false);
try {
if (isDebugEnabled) {
logger.debug("Executing beforeCompletion() notification for transaction {} after failover", clientMessage.getTransactionId());
}
txState.setIsJTA(true);
txState.beforeCompletion();
} finally {
txMgr.unmasquerade(txState);
}
}
afterCompletion.run();
}
}
} catch (Exception e) {
writeException(clientMessage, MessageType.EXCEPTION, e, false, serverConnection);
serverConnection.setAsTrue(RESPONDED);
}
if (isDebugEnabled) {
logger.debug("Sent tx synchronization response");
}
}
}
Aggregations