Permalink
Show file tree
Hide file tree
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
GERONIMO-5152 Add retry tasks for recovery and retry errors on commit
git-svn-id: https://svn.apache.org/repos/asf/geronimo/components/txmanager/trunk@912058 13f79535-47bb-0310-9956-ffa450edef68
- Loading branch information
Showing
14 changed files
with
387 additions
and
100 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1,140 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
|
||
package org.apache.geronimo.transaction.manager; | ||
|
||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.TimerTask; | ||
|
||
import javax.transaction.HeuristicMixedException; | ||
import javax.transaction.HeuristicRollbackException; | ||
import javax.transaction.Status; | ||
import javax.transaction.SystemException; | ||
import javax.transaction.xa.XAException; | ||
import javax.transaction.xa.Xid; | ||
|
||
import org.apache.geronimo.transaction.manager.TransactionImpl.TransactionBranch; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
/** | ||
* @version $Rev$ $Date$ | ||
*/ | ||
public class CommitTask extends TimerTask { | ||
private static final Logger log = LoggerFactory.getLogger(CommitTask.class); | ||
private final Xid xid; | ||
private final List<TransactionBranch> rms; | ||
private final Object logMark; | ||
private final RetryScheduler retryScheduler; | ||
private final TransactionLog txLog; | ||
private int count = 0; | ||
private int status; | ||
private XAException cause; | ||
|
||
public CommitTask(Xid xid, List<TransactionBranch> rms, Object logMark, RetryScheduler retryScheduler, TransactionLog txLog) { | ||
this.xid = xid; | ||
this.rms = rms; | ||
this.logMark = logMark; | ||
this.retryScheduler = retryScheduler; | ||
this.txLog = txLog; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
synchronized (this) { | ||
status = Status.STATUS_COMMITTING; | ||
} | ||
for (Iterator i = rms.iterator(); i.hasNext();) { | ||
TransactionBranch manager = (TransactionBranch) i.next(); | ||
try { | ||
try { | ||
manager.getCommitter().commit(manager.getBranchId(), false); | ||
i.remove(); | ||
} catch (XAException e) { | ||
log.error("Unexpected exception committing " + manager.getCommitter() + "; continuing to commit other RMs", e); | ||
|
||
if (e.errorCode == XAException.XA_HEURRB) { | ||
i.remove(); | ||
log.info("Transaction has been heuristically rolled back"); | ||
cause = e; | ||
manager.getCommitter().forget(manager.getBranchId()); | ||
} else if (e.errorCode == XAException.XA_HEURMIX) { | ||
i.remove(); | ||
log.info("Transaction has been heuristically committed and rolled back"); | ||
cause = e; | ||
manager.getCommitter().forget(manager.getBranchId()); | ||
} else if (e.errorCode == XAException.XA_HEURCOM) { | ||
i.remove(); | ||
// let's not throw an exception as the transaction has been committed | ||
log.info("Transaction has been heuristically committed"); | ||
manager.getCommitter().forget(manager.getBranchId()); | ||
} else if (e.errorCode == XAException.XA_RETRY) { | ||
// do nothing, retry later | ||
} else { | ||
//nothing we can do about it.... keep trying | ||
i.remove(); | ||
cause = e; | ||
} | ||
} | ||
} catch (XAException e) { | ||
if (e.errorCode == XAException.XAER_NOTA) { | ||
// NOTA in response to forget, means the resource already forgot the transaction | ||
// ignore | ||
} else { | ||
cause = e; | ||
} | ||
} | ||
} | ||
//if all resources were read only, we didn't write a prepare record. | ||
if (rms.isEmpty() && status == Status.STATUS_COMMITTED) { | ||
try { | ||
txLog.commit(xid, logMark); | ||
synchronized (this) { | ||
status = Status.STATUS_COMMITTED; | ||
} | ||
} catch (LogException e) { | ||
log.error("Unexpected exception logging commit completion for xid " + xid, e); | ||
cause = (XAException) new XAException("Unexpected error logging commit completion for xid " + xid).initCause(e); | ||
} | ||
} else { | ||
retryScheduler.retry(this, count++); | ||
} | ||
// if (cause != null) { | ||
// if (cause.errorCode == XAException.XA_HEURRB && !evercommit) { | ||
// throw (HeuristicRollbackException) new HeuristicRollbackException("Error during two phase commit").initCause(cause); | ||
// } else if (cause.errorCode == XAException.XA_HEURRB && evercommit) { | ||
// throw (HeuristicMixedException) new HeuristicMixedException("Error during two phase commit").initCause(cause); | ||
// } else if (cause.errorCode == XAException.XA_HEURMIX) { | ||
// throw (HeuristicMixedException) new HeuristicMixedException("Error during two phase commit").initCause(cause); | ||
// } else { | ||
// throw (SystemException) new SystemException("Error during two phase commit").initCause(cause); | ||
// } | ||
// } | ||
} | ||
|
||
public XAException getCause() { | ||
return cause; | ||
} | ||
|
||
public int getStatus() { | ||
return status; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1,39 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
|
||
package org.apache.geronimo.transaction.manager; | ||
|
||
import java.util.Timer; | ||
import java.util.TimerTask; | ||
|
||
/** | ||
* @version $Rev$ $Date$ | ||
*/ | ||
public class ExponentialtIntervalRetryScheduler implements RetryScheduler{ | ||
|
||
private final Timer timer = new Timer(); | ||
|
||
private final int base = 2; | ||
|
||
public void retry(TimerTask task, int count) { | ||
long interval = Math.round(Math.pow(base, count)) * 1000; | ||
timer.schedule(task, interval); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1,63 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
|
||
package org.apache.geronimo.transaction.manager; | ||
|
||
import java.util.TimerTask; | ||
|
||
import javax.transaction.SystemException; | ||
import javax.transaction.xa.XAException; | ||
|
||
/** | ||
* @version $Rev$ $Date$ | ||
*/ | ||
public class RecoverTask extends TimerTask { | ||
|
||
private final RetryScheduler retryScheduler; | ||
private final NamedXAResourceFactory namedXAResourceFactory; | ||
private final Recovery recovery; | ||
private final RecoverableTransactionManager recoverableTransactionManager; | ||
private int count = 0; | ||
|
||
public RecoverTask(RetryScheduler retryScheduler, NamedXAResourceFactory namedXAResourceFactory, Recovery recovery, RecoverableTransactionManager recoverableTransactionManager) { | ||
this.retryScheduler = retryScheduler; | ||
this.namedXAResourceFactory = namedXAResourceFactory; | ||
this.recovery = recovery; | ||
this.recoverableTransactionManager = recoverableTransactionManager; | ||
} | ||
|
||
@Override | ||
public void run() { | ||
try { | ||
NamedXAResource namedXAResource = namedXAResourceFactory.getNamedXAResource(); | ||
try { | ||
recovery.recoverResourceManager(namedXAResource); | ||
} finally { | ||
namedXAResourceFactory.returnNamedXAResource(namedXAResource); | ||
} | ||
return; | ||
} catch (XAException e) { | ||
recoverableTransactionManager.recoveryError(e); | ||
} catch (SystemException e) { | ||
recoverableTransactionManager.recoveryError(e); | ||
} | ||
retryScheduler.retry(this, count++); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@@ -0,0 +1,31 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one | ||
* or more contributor license agreements. See the NOTICE file | ||
* distributed with this work for additional information | ||
* regarding copyright ownership. The ASF licenses this file | ||
* to you under the Apache License, Version 2.0 (the | ||
* "License"); you may not use this file except in compliance | ||
* with the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
|
||
package org.apache.geronimo.transaction.manager; | ||
|
||
import java.util.TimerTask; | ||
|
||
/** | ||
* @version $Rev$ $Date$ | ||
*/ | ||
public interface RetryScheduler { | ||
|
||
void retry(TimerTask task, int count); | ||
} |
Oops, something went wrong.