ConnectionHandle con = this.connectionHandle.get();
if (con == null){ // safety!
throw PoolUtil.generateSQLException("ConnectionHandle is gone!", new IllegalStateException());
}
TransactionRecoveryResult recoveryResult = con.recoveryResult;
ConnectionHook connectionHook = con.getPool().getConfig().getConnectionHook();
int acquireRetryAttempts = con.getPool().getConfig().getAcquireRetryAttempts();
long acquireRetryDelay = con.getPool().getConfig().getAcquireRetryDelayInMs();
AcquireFailConfig acquireConfig = new AcquireFailConfig();
acquireConfig.setAcquireRetryAttempts(new AtomicInteger(acquireRetryAttempts));
acquireConfig.setAcquireRetryDelayInMs(acquireRetryDelay);
acquireConfig.setLogMessage("Failed to replay transaction");
Map<Object, Object> replaceTarget = new HashMap<Object, Object>();
do{
replaceTarget.clear();
// make a copy
for (Entry<Object, Object> entry: recoveryResult.getReplaceTarget().entrySet()){
replaceTarget.put(entry.getKey(), entry.getValue());
}
List<PreparedStatement> prepStatementTarget = new ArrayList<PreparedStatement>();
List<CallableStatement> callableStatementTarget = new ArrayList<CallableStatement>();
List<Statement> statementTarget = new ArrayList<Statement>();
Object result = null;
tryAgain = false;
// this connection is dead
con.setInReplayMode(true); // don't go in a loop of saving our saved log!
try{
con.clearStatementCaches(true);
con.getInternalConnection().close();
} catch(Throwable t){
// do nothing - also likely to fail here
}
try{
con.setInternalConnection(memorize(con.getPool().obtainInternalConnection(con), con));
} catch(SQLException e){
throw con.markPossiblyBroken(e);
}
con.getOriginatingPartition().trackConnectionFinalizer(con); // track this too.
for (ReplayLog replay: oldReplayLog){
// we got new connections/statement handles so replace what we've got with the new ones
if (replay.getTarget() instanceof Connection){
replaceTarget.put(replay.getTarget(), con.getInternalConnection());
} else if (replay.getTarget() instanceof CallableStatement){
if (replaceTarget.get(replay.getTarget()) == null){
replaceTarget.put(replay.getTarget(), callableStatementTarget.remove(0));
}
} else if (replay.getTarget() instanceof PreparedStatement){
if (replaceTarget.get(replay.getTarget()) == null){
replaceTarget.put(replay.getTarget(), prepStatementTarget.remove(0));
}
}else if (replay.getTarget() instanceof Statement){
if (replaceTarget.get(replay.getTarget()) == null){
replaceTarget.put(replay.getTarget(), statementTarget.remove(0));
}
}
try {
// run again using the new connection/statement
// result = replay.getMethod().invoke(, replay.getArgs());
result = runWithPossibleProxySwap(replay.getMethod(), replaceTarget.get(replay.getTarget()), replay.getArgs());
// remember what we've got last
recoveryResult.setResult(result);
// if we got a new statement (eg a prepareStatement call), save it, we'll use it for our search/replace
if (result instanceof CallableStatement){
callableStatementTarget.add((CallableStatement)result);
} else if (result instanceof PreparedStatement){
prepStatementTarget.add((PreparedStatement)result);
} else if (result instanceof Statement){
statementTarget.add((Statement)result);
}
} catch (Throwable t) {
// It blew up again, let's try a couple more times before giving up...
// call the hook, if available.
if (connectionHook != null){
tryAgain = connectionHook.onAcquireFail(t, acquireConfig);
} else {
logger.error("Failed to replay transaction. Sleeping for "+acquireRetryDelay+"ms and trying again. Attempts left: "+acquireRetryAttempts+". Exception: "+t.getCause() + " Message:"+t.getMessage());
try {