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:
Britt Park
2006-09-03 06:30:05 +00:00
parent 7c70be1811
commit 0b58cca272
10 changed files with 181 additions and 1000 deletions

View File

@@ -31,6 +31,8 @@ import org.alfresco.service.cmr.avm.AVMException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService;
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)
{
e.printStackTrace(System.err);
if (e instanceof AVMException)
{
return;
@@ -230,7 +233,14 @@ class AVMCrawler implements Runnable
{
return;
}
e.printStackTrace(System.err);
if (e instanceof ConcurrencyFailureException)
{
return;
}
if (e instanceof HibernateException)
{
return;
}
throw new AVMException("Failure", e);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,9 @@
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.
* @author britt
@@ -34,9 +37,9 @@ public class Issuer
private String fName;
/**
* The transactional wrapper.
* The transaction service.
*/
private RetryingTransactionHelper fTransaction;
private TransactionService fTransactionService;
/**
* Default constructor.
@@ -54,38 +57,33 @@ public class Issuer
fName = name;
}
/**
* Set the transactional wrapper.
* @param retryingTransaction The transactional wrapper.
*/
public void setRetryingTransaction(RetryingTransactionHelper retryingTransaction)
public void setTransactionService(TransactionService transactionService)
{
fTransaction = retryingTransaction;
fTransactionService = transactionService;
}
/**
* After the database is up, get our value.
*/
public void init()
{
class TxnCallback implements RetryingTransactionCallback
class TxnWork implements TransactionUtil.TransactionWork<Long>
{
public Long value;
public void perform()
public Long doWork() throws Exception
{
value = AVMContext.fgInstance.fIssuerDAO.getIssuerValue(fName);
return AVMContext.fgInstance.fIssuerDAO.getIssuerValue(fName);
}
};
TxnCallback doit = new TxnCallback();
fTransaction.perform(doit, false);
if (doit.value == null)
}
Long result = TransactionUtil.executeInUserTransaction(fTransactionService,
new TxnWork(),
true);
if (result == null)
{
fNext = 0L;
}
else
{
fNext = doit.value + 1;
fNext = result + 1L;
}
}

View File

@@ -20,6 +20,8 @@ package org.alfresco.repo.avm;
import java.util.LinkedList;
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.LogFactory;
@@ -31,10 +33,11 @@ import org.apache.commons.logging.LogFactory;
public class OrphanReaper implements Runnable
{
private Log fgLogger = LogFactory.getLog(OrphanReaper.class);
/**
* The HibernateTxn instance.
* The Transaction Service
*/
private RetryingTransactionHelper fTransaction;
private TransactionService fTransactionService;
/**
* Inactive base sleep interval.
@@ -119,13 +122,9 @@ public class OrphanReaper implements Runnable
fBatchSize = size;
}
/**
* Set the Hibernate Transaction Wrapper.
* @param transaction
*/
public void setRetryingTransaction(RetryingTransactionHelper transaction)
public void setTransactionService(TransactionService transactionService)
{
fTransaction = transaction;
fTransactionService = transactionService;
}
/**
@@ -213,9 +212,10 @@ public class OrphanReaper implements Runnable
*/
public void doBatch()
{
class TxnCallback implements RetryingTransactionCallback
class TxnWork implements TransactionUtil.TransactionWork<Object>
{
public void perform()
public Object doWork()
throws Exception
{
if (fPurgeQueue == null)
{
@@ -223,7 +223,7 @@ public class OrphanReaper implements Runnable
if (nodes.size() == 0)
{
fActive = false;
return;
return null;
}
fPurgeQueue = new LinkedList<Long>();
for (AVMNode node : nodes)
@@ -237,7 +237,7 @@ public class OrphanReaper implements Runnable
if (fPurgeQueue.size() == 0)
{
fPurgeQueue = null;
return;
return null;
}
AVMNode node = AVMContext.fgInstance.fAVMNodeDAO.getByID(fPurgeQueue.removeFirst());
// 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);
}
}
return null;
}
}
try
{
TxnCallback doit = new TxnCallback();
fTransaction.perform(doit, true);
TransactionUtil.executeInUserTransaction(fTransactionService,
new TxnWork());
}
catch (Exception e)
{

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}