mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Removed RetryingTransactionHelper and friends. AVMService's transactional
behavior is now declaratively specified. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3662 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -7,22 +7,22 @@
|
|||||||
<!-- ID Issuers. -->
|
<!-- ID Issuers. -->
|
||||||
|
|
||||||
<bean id="nodeIssuer" class="org.alfresco.repo.avm.Issuer"
|
<bean id="nodeIssuer" class="org.alfresco.repo.avm.Issuer"
|
||||||
depends-on="retryingTransaction,avmContext" init-method="init">
|
depends-on="avmContext" init-method="init">
|
||||||
<property name="name">
|
<property name="name">
|
||||||
<value>node</value>
|
<value>node</value>
|
||||||
</property>
|
</property>
|
||||||
<property name="retryingTransaction">
|
<property name="transactionService">
|
||||||
<ref bean="retryingTransaction"/>
|
<ref bean="transactionComponent"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="layerIssuer" class="org.alfresco.repo.avm.Issuer"
|
<bean id="layerIssuer" class="org.alfresco.repo.avm.Issuer"
|
||||||
depends-on="retryingTransaction,avmContext" init-method="init">
|
depends-on="avmContext" init-method="init">
|
||||||
<property name="name">
|
<property name="name">
|
||||||
<value>layer</value>
|
<value>layer</value>
|
||||||
</property>
|
</property>
|
||||||
<property name="retryingTransaction">
|
<property name="transactionService">
|
||||||
<ref bean="retryingTransaction"/>
|
<ref bean="transactionComponent"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
@@ -141,45 +141,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<!-- A read only DefaultTransactionDefinition -->
|
|
||||||
<bean id="readTransactionDefinition"
|
|
||||||
class="org.springframework.transaction.support.DefaultTransactionDefinition">
|
|
||||||
<property name="propagationBehaviorName">
|
|
||||||
<value>PROPAGATION_REQUIRED</value>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<value>true</value>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!-- A write DefaultTransactionDefinition -->
|
|
||||||
<bean id="writeTransactionDefinition"
|
|
||||||
class="org.springframework.transaction.support.DefaultTransactionDefinition">
|
|
||||||
<property name="propagationBehaviorName">
|
|
||||||
<value>PROPAGATION_REQUIRED</value>
|
|
||||||
</property>
|
|
||||||
<property name="readOnly">
|
|
||||||
<value>false</value>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<!-- The Retrying Transaction Helper. -->
|
|
||||||
<bean id="retryingTransaction"
|
|
||||||
class="org.alfresco.repo.avm.hibernate.HibernateRetryingTransactionHelper">
|
|
||||||
<property name="sessionFactory">
|
|
||||||
<ref bean="sessionFactory"/>
|
|
||||||
</property>
|
|
||||||
<property name="transactionManager">
|
|
||||||
<ref bean="transactionManager"/>
|
|
||||||
</property>
|
|
||||||
<property name="readTransactionDefinition">
|
|
||||||
<ref bean="readTransactionDefinition"/>
|
|
||||||
</property>
|
|
||||||
<property name="writeTransactionDefinition">
|
|
||||||
<ref bean="writeTransactionDefinition"/>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="orphanReaper" class="org.alfresco.repo.avm.OrphanReaper"
|
<bean id="orphanReaper" class="org.alfresco.repo.avm.OrphanReaper"
|
||||||
init-method="init" destroy-method="shutDown" depends-on="AVMService">
|
init-method="init" destroy-method="shutDown" depends-on="AVMService">
|
||||||
<property name="inactiveBaseSleep">
|
<property name="inactiveBaseSleep">
|
||||||
@@ -194,8 +155,8 @@
|
|||||||
<property name="maxQueueLength">
|
<property name="maxQueueLength">
|
||||||
<value>1000</value>
|
<value>1000</value>
|
||||||
</property>
|
</property>
|
||||||
<property name="retryingTransaction">
|
<property name="transactionService">
|
||||||
<ref bean="retryingTransaction"/>
|
<ref bean="transactionComponent"/>
|
||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
@@ -1007,9 +1007,6 @@
|
|||||||
<!-- The AVMService -->
|
<!-- The AVMService -->
|
||||||
|
|
||||||
<bean id="avmService" class="org.alfresco.repo.avm.AVMServiceImpl">
|
<bean id="avmService" class="org.alfresco.repo.avm.AVMServiceImpl">
|
||||||
<property name="retryingTransaction">
|
|
||||||
<ref bean="retryingTransaction"/>
|
|
||||||
</property>
|
|
||||||
<property name="avmRepository">
|
<property name="avmRepository">
|
||||||
<ref bean="avmRepository"/>
|
<ref bean="avmRepository"/>
|
||||||
</property>
|
</property>
|
||||||
@@ -1024,6 +1021,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="interceptorNames">
|
<property name="interceptorNames">
|
||||||
<list>
|
<list>
|
||||||
|
<idref local="AVMService_transaction"/>
|
||||||
<idref local="AVMService_descriptor"/>
|
<idref local="AVMService_descriptor"/>
|
||||||
</list>
|
</list>
|
||||||
</property>
|
</property>
|
||||||
@@ -1038,6 +1036,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
|
<bean id="AVMService_transaction" class="org.springframework.transaction.interceptor.TransactionInterceptor">
|
||||||
|
<property name="transactionManager">
|
||||||
|
<ref bean="transactionManager"/>
|
||||||
|
</property>
|
||||||
|
<property name="transactionAttributes">
|
||||||
|
<props>
|
||||||
|
<prop key="hasAspect">${server.transaction.mode.readOnly}</prop>
|
||||||
|
<prop key="getContentDataForWrite">${server.transaction.mode.default}</prop>
|
||||||
|
<prop key="getFileOutputStream">${server.transaction.mode.default}</prop>
|
||||||
|
<prop key="get*">${server.transaction.mode.readOnly}</prop>
|
||||||
|
<prop key="lookup">${server.transaction.mode.readOnly}</prop>
|
||||||
|
<prop key="*">${server.transaction.mode.default}</prop>
|
||||||
|
</props>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Workflow Service -->
|
<!-- Workflow Service -->
|
||||||
|
|
||||||
<bean id="WorkflowService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
<bean id="WorkflowService" class="org.springframework.aop.framework.ProxyFactoryBean">
|
||||||
|
@@ -31,6 +31,8 @@ import org.alfresco.service.cmr.avm.AVMException;
|
|||||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||||
import org.alfresco.service.cmr.avm.AVMService;
|
import org.alfresco.service.cmr.avm.AVMService;
|
||||||
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
import org.alfresco.service.cmr.avm.AVMStoreDescriptor;
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,6 +224,7 @@ class AVMCrawler implements Runnable
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
e.printStackTrace(System.err);
|
||||||
if (e instanceof AVMException)
|
if (e instanceof AVMException)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -230,7 +233,14 @@ class AVMCrawler implements Runnable
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e.printStackTrace(System.err);
|
if (e instanceof ConcurrencyFailureException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (e instanceof HibernateException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
throw new AVMException("Failure", e);
|
throw new AVMException("Failure", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
package org.alfresco.repo.avm;
|
package org.alfresco.repo.avm;
|
||||||
|
|
||||||
|
import org.alfresco.repo.transaction.TransactionUtil;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a helper class that knows how to issue identifiers.
|
* This is a helper class that knows how to issue identifiers.
|
||||||
* @author britt
|
* @author britt
|
||||||
@@ -34,9 +37,9 @@ public class Issuer
|
|||||||
private String fName;
|
private String fName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transactional wrapper.
|
* The transaction service.
|
||||||
*/
|
*/
|
||||||
private RetryingTransactionHelper fTransaction;
|
private TransactionService fTransactionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
@@ -54,13 +57,9 @@ public class Issuer
|
|||||||
fName = name;
|
fName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setTransactionService(TransactionService transactionService)
|
||||||
* Set the transactional wrapper.
|
|
||||||
* @param retryingTransaction The transactional wrapper.
|
|
||||||
*/
|
|
||||||
public void setRetryingTransaction(RetryingTransactionHelper retryingTransaction)
|
|
||||||
{
|
{
|
||||||
fTransaction = retryingTransaction;
|
fTransactionService = transactionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,24 +67,23 @@ public class Issuer
|
|||||||
*/
|
*/
|
||||||
public void init()
|
public void init()
|
||||||
{
|
{
|
||||||
class TxnCallback implements RetryingTransactionCallback
|
class TxnWork implements TransactionUtil.TransactionWork<Long>
|
||||||
{
|
{
|
||||||
public Long value;
|
public Long doWork() throws Exception
|
||||||
|
|
||||||
public void perform()
|
|
||||||
{
|
{
|
||||||
value = AVMContext.fgInstance.fIssuerDAO.getIssuerValue(fName);
|
return AVMContext.fgInstance.fIssuerDAO.getIssuerValue(fName);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
TxnCallback doit = new TxnCallback();
|
Long result = TransactionUtil.executeInUserTransaction(fTransactionService,
|
||||||
fTransaction.perform(doit, false);
|
new TxnWork(),
|
||||||
if (doit.value == null)
|
true);
|
||||||
|
if (result == null)
|
||||||
{
|
{
|
||||||
fNext = 0L;
|
fNext = 0L;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fNext = doit.value + 1;
|
fNext = result + 1L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,6 +20,8 @@ package org.alfresco.repo.avm;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.alfresco.repo.transaction.TransactionUtil;
|
||||||
|
import org.alfresco.service.transaction.TransactionService;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
@@ -31,10 +33,11 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
public class OrphanReaper implements Runnable
|
public class OrphanReaper implements Runnable
|
||||||
{
|
{
|
||||||
private Log fgLogger = LogFactory.getLog(OrphanReaper.class);
|
private Log fgLogger = LogFactory.getLog(OrphanReaper.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The HibernateTxn instance.
|
* The Transaction Service
|
||||||
*/
|
*/
|
||||||
private RetryingTransactionHelper fTransaction;
|
private TransactionService fTransactionService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inactive base sleep interval.
|
* Inactive base sleep interval.
|
||||||
@@ -119,13 +122,9 @@ public class OrphanReaper implements Runnable
|
|||||||
fBatchSize = size;
|
fBatchSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void setTransactionService(TransactionService transactionService)
|
||||||
* Set the Hibernate Transaction Wrapper.
|
|
||||||
* @param transaction
|
|
||||||
*/
|
|
||||||
public void setRetryingTransaction(RetryingTransactionHelper transaction)
|
|
||||||
{
|
{
|
||||||
fTransaction = transaction;
|
fTransactionService = transactionService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -213,9 +212,10 @@ public class OrphanReaper implements Runnable
|
|||||||
*/
|
*/
|
||||||
public void doBatch()
|
public void doBatch()
|
||||||
{
|
{
|
||||||
class TxnCallback implements RetryingTransactionCallback
|
class TxnWork implements TransactionUtil.TransactionWork<Object>
|
||||||
{
|
{
|
||||||
public void perform()
|
public Object doWork()
|
||||||
|
throws Exception
|
||||||
{
|
{
|
||||||
if (fPurgeQueue == null)
|
if (fPurgeQueue == null)
|
||||||
{
|
{
|
||||||
@@ -223,7 +223,7 @@ public class OrphanReaper implements Runnable
|
|||||||
if (nodes.size() == 0)
|
if (nodes.size() == 0)
|
||||||
{
|
{
|
||||||
fActive = false;
|
fActive = false;
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
fPurgeQueue = new LinkedList<Long>();
|
fPurgeQueue = new LinkedList<Long>();
|
||||||
for (AVMNode node : nodes)
|
for (AVMNode node : nodes)
|
||||||
@@ -237,7 +237,7 @@ public class OrphanReaper implements Runnable
|
|||||||
if (fPurgeQueue.size() == 0)
|
if (fPurgeQueue.size() == 0)
|
||||||
{
|
{
|
||||||
fPurgeQueue = null;
|
fPurgeQueue = null;
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
AVMNode node = AVMContext.fgInstance.fAVMNodeDAO.getByID(fPurgeQueue.removeFirst());
|
AVMNode node = AVMContext.fgInstance.fAVMNodeDAO.getByID(fPurgeQueue.removeFirst());
|
||||||
// Save away the ancestor and merged from fields from this node.
|
// Save away the ancestor and merged from fields from this node.
|
||||||
@@ -303,12 +303,13 @@ public class OrphanReaper implements Runnable
|
|||||||
AVMContext.fgInstance.fAVMNodeDAO.delete(node);
|
AVMContext.fgInstance.fAVMNodeDAO.delete(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
TxnCallback doit = new TxnCallback();
|
TransactionUtil.executeInUserTransaction(fTransactionService,
|
||||||
fTransaction.perform(doit, true);
|
new TxnWork());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2006 Alfresco, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Mozilla Public License version 1.1
|
|
||||||
* with a permitted attribution clause. You may obtain a
|
|
||||||
* copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.alfresco.org/legal/license.txt
|
|
||||||
*
|
|
||||||
* 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.alfresco.repo.avm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Worker object for AVM Retrying Transactions.
|
|
||||||
* @author britt
|
|
||||||
*/
|
|
||||||
public interface RetryingTransactionCallback
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Do our work.
|
|
||||||
*/
|
|
||||||
public void perform();
|
|
||||||
}
|
|
@@ -1,18 +0,0 @@
|
|||||||
package org.alfresco.repo.avm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for a retrying transaction. All operations, so far,
|
|
||||||
* in the AVM repository are idempotent and can thus be retried
|
|
||||||
* when a transaction fails for synchronization reasons.
|
|
||||||
* @author britt
|
|
||||||
*/
|
|
||||||
public interface RetryingTransactionHelper
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Perform a set of operations under a single transaction.
|
|
||||||
* Keep trying if the operation fails because of a concurrency issue.
|
|
||||||
* @param callback The worker.
|
|
||||||
* @param write Whether this is a write operation.
|
|
||||||
*/
|
|
||||||
public void perform(RetryingTransactionCallback callback, boolean write);
|
|
||||||
}
|
|
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2006 Alfresco, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Mozilla Public License version 1.1
|
|
||||||
* with a permitted attribution clause. You may obtain a
|
|
||||||
* copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.alfresco.org/legal/license.txt
|
|
||||||
*
|
|
||||||
* 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.alfresco.repo.avm.hibernate;
|
|
||||||
|
|
||||||
import java.sql.SQLException;
|
|
||||||
|
|
||||||
import org.alfresco.repo.avm.RetryingTransactionCallback;
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.Session;
|
|
||||||
import org.springframework.orm.hibernate3.HibernateCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a wrapper around HibernateTxnCallback implementation.
|
|
||||||
* @author britt
|
|
||||||
*/
|
|
||||||
class HibernateCallbackWrapper implements HibernateCallback
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The HibernateTxnCallback to execute.
|
|
||||||
*/
|
|
||||||
private RetryingTransactionCallback fCallback;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make one up.
|
|
||||||
* @param callback
|
|
||||||
*/
|
|
||||||
public HibernateCallbackWrapper(RetryingTransactionCallback callback)
|
|
||||||
{
|
|
||||||
fCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call the HibernateTxnCallback internally.
|
|
||||||
* @param session The Hibernate Session.
|
|
||||||
*/
|
|
||||||
public Object doInHibernate(Session session) throws HibernateException,
|
|
||||||
SQLException
|
|
||||||
{
|
|
||||||
fCallback.perform();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,179 +0,0 @@
|
|||||||
package org.alfresco.repo.avm.hibernate;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2006 Alfresco, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Mozilla Public License version 1.1
|
|
||||||
* with a permitted attribution clause. You may obtain a
|
|
||||||
* copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.alfresco.org/legal/license.txt
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.alfresco.repo.avm.RetryingTransactionCallback;
|
|
||||||
import org.alfresco.repo.avm.RetryingTransactionHelper;
|
|
||||||
import org.alfresco.service.cmr.avm.AVMException;
|
|
||||||
import org.alfresco.service.cmr.avm.AVMNotFoundException;
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
import org.springframework.dao.DataRetrievalFailureException;
|
|
||||||
import org.springframework.dao.DeadlockLoserDataAccessException;
|
|
||||||
import org.springframework.dao.OptimisticLockingFailureException;
|
|
||||||
import org.springframework.orm.hibernate3.HibernateTemplate;
|
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
|
||||||
import org.springframework.transaction.TransactionDefinition;
|
|
||||||
import org.springframework.transaction.TransactionStatus;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for DAOs.
|
|
||||||
* @author britt
|
|
||||||
*/
|
|
||||||
public class HibernateRetryingTransactionHelper extends HibernateTemplate implements RetryingTransactionHelper
|
|
||||||
{
|
|
||||||
private static Logger fgLogger = Logger.getLogger(HibernateRetryingTransactionHelper.class);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The transaction manager.
|
|
||||||
*/
|
|
||||||
private PlatformTransactionManager fTransactionManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The read transaction definition.
|
|
||||||
*/
|
|
||||||
private TransactionDefinition fReadDefinition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The write transaction definition.
|
|
||||||
*/
|
|
||||||
private TransactionDefinition fWriteDefinition;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The random number generator for inter-retry sleep.
|
|
||||||
*/
|
|
||||||
private Random fRandom;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make one up.
|
|
||||||
* @param sessionFactory The SessionFactory.
|
|
||||||
*/
|
|
||||||
public HibernateRetryingTransactionHelper()
|
|
||||||
{
|
|
||||||
fRandom = new Random();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run an idempotent transaction, repeating invocations as necessary
|
|
||||||
* for failures caused by deadlocks and lost races.
|
|
||||||
* @param callback The callback containging the work to do.
|
|
||||||
* @param write Whether this is a write transaction.
|
|
||||||
*/
|
|
||||||
public void perform(RetryingTransactionCallback callback, boolean write)
|
|
||||||
{
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
TransactionStatus status = null;
|
|
||||||
boolean newTxn = true;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
status =
|
|
||||||
fTransactionManager.getTransaction(write ? fWriteDefinition : fReadDefinition);
|
|
||||||
newTxn = status.isNewTransaction();
|
|
||||||
execute(new HibernateCallbackWrapper(callback));
|
|
||||||
if (newTxn)
|
|
||||||
{
|
|
||||||
fTransactionManager.commit(status);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Throwable t)
|
|
||||||
{
|
|
||||||
if (status == null)
|
|
||||||
{
|
|
||||||
t.printStackTrace(System.err);
|
|
||||||
throw new AVMException("Unrecoverable error.", t);
|
|
||||||
}
|
|
||||||
if (newTxn && !status.isCompleted())
|
|
||||||
{
|
|
||||||
fTransactionManager.rollback(status);
|
|
||||||
}
|
|
||||||
if (!newTxn)
|
|
||||||
{
|
|
||||||
if (t instanceof RuntimeException)
|
|
||||||
{
|
|
||||||
throw (RuntimeException)t;
|
|
||||||
}
|
|
||||||
throw new AVMException("Unrecoverable error.", t);
|
|
||||||
}
|
|
||||||
// If we've lost a race or we've deadlocked, retry.
|
|
||||||
if (t instanceof DeadlockLoserDataAccessException)
|
|
||||||
{
|
|
||||||
fgLogger.info("Deadlock");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
long interval;
|
|
||||||
synchronized (fRandom)
|
|
||||||
{
|
|
||||||
interval = fRandom.nextInt(1000);
|
|
||||||
}
|
|
||||||
Thread.sleep(interval);
|
|
||||||
}
|
|
||||||
catch (InterruptedException ie)
|
|
||||||
{
|
|
||||||
// Do nothing.
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (t instanceof OptimisticLockingFailureException)
|
|
||||||
{
|
|
||||||
fgLogger.info("Lost Race");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (t instanceof AVMException)
|
|
||||||
{
|
|
||||||
throw (AVMException)t;
|
|
||||||
}
|
|
||||||
if (t instanceof DataRetrievalFailureException)
|
|
||||||
{
|
|
||||||
System.err.println("Data Retrieval Error.");
|
|
||||||
throw new AVMNotFoundException("Object not found.", t);
|
|
||||||
}
|
|
||||||
throw new AVMException("Unrecoverable error.", t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the transaction manager we are operating under.
|
|
||||||
* @param manager
|
|
||||||
*/
|
|
||||||
public void setTransactionManager(PlatformTransactionManager manager)
|
|
||||||
{
|
|
||||||
fTransactionManager = manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the read Transaction Definition.
|
|
||||||
* @param def
|
|
||||||
*/
|
|
||||||
public void setReadTransactionDefinition(TransactionDefinition def)
|
|
||||||
{
|
|
||||||
fReadDefinition = def;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the write Transaction Definition.
|
|
||||||
* @param def
|
|
||||||
*/
|
|
||||||
public void setWriteTransactionDefinition(TransactionDefinition def)
|
|
||||||
{
|
|
||||||
fWriteDefinition = def;
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user