[exo-jcr-commits] exo-jcr SVN: r1440 - in jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent: jbosscache and 1 other directory.
do-not-reply at jboss.org
do-not-reply at jboss.org
Sun Jan 17 03:19:24 EST 2010
Author: pnedonosko
Date: 2010-01-17 03:19:24 -0500 (Sun, 17 Jan 2010)
New Revision: 1440
Added:
jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java
Modified:
jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
Log:
EXOJCR-405 isolated XA transactions for storage operations (cache now)
Modified: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
--- jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2010-01-17 08:09:07 UTC (rev 1439)
+++ jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2010-01-17 08:19:24 UTC (rev 1440)
@@ -25,7 +25,6 @@
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.JBossCacheWorkspaceStorageCache;
-import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
import org.exoplatform.services.transaction.TransactionService;
@@ -35,14 +34,12 @@
import java.util.Map;
import java.util.concurrent.CountDownLatch;
-import javax.jcr.InvalidItemStateException;
-import javax.jcr.ItemExistsException;
import javax.jcr.RepositoryException;
-import javax.transaction.InvalidTransactionException;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
-import javax.transaction.Status;
import javax.transaction.SystemException;
-import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
/**
@@ -52,7 +49,7 @@
* Author : Peter Nedonosko peter.nedonosko at exoplatform.com.ua
* 13.04.2006
*
- * @version $Id: CacheableWorkspaceDataManager.java 34801 2009-07-31 15:44:50Z dkatayev $
+ * @version $Id$
*/
public class CacheableWorkspaceDataManager extends WorkspacePersistentDataManager
{
@@ -251,6 +248,139 @@
}
}
+ protected abstract class StorageTxIsolatedOperation extends TxIsolatedOperation
+ {
+ StorageTxIsolatedOperation()
+ {
+ super(transactionManager);
+ }
+
+ protected void beginTx() throws NotSupportedException, SystemException
+ {
+ super.beginTx(); // start new global tx
+ cache.beginTransaction(); // TODO keep it into the cache impl
+ }
+
+ protected void commitTx() throws SecurityException, IllegalStateException, RollbackException,
+ HeuristicMixedException, HeuristicRollbackException, SystemException
+ {
+ cache.commitTransaction();
+ super.commitTx(); // commit global tx
+ }
+
+ protected void rollbackTx() throws NotSupportedException, SystemException
+ {
+ cache.rollbackTransaction();
+ super.rollbackTx(); // rollback global tx
+ }
+ }
+
+ protected class SaveInTransaction extends StorageTxIsolatedOperation
+ {
+ final ItemStateChangesLog changes;
+
+ SaveInTransaction(ItemStateChangesLog changes)
+ {
+ this.changes = changes;
+ }
+
+ @Override
+ protected void action() throws RepositoryException
+ {
+ CacheableWorkspaceDataManager.super.save(changes);
+ }
+
+ @Override
+ protected void txAction() throws RepositoryException
+ {
+ super.txAction();
+
+ // notify listeners after transaction commit but before the current resume!
+ try
+ {
+ notifySaveItems(changes, false);
+ }
+ catch (Throwable th)
+ {
+ // TODO XA layer can throws runtime exceptions
+ throw new RepositoryException(th);
+ }
+ }
+ }
+
+ protected class CacheNodesInTransaction extends StorageTxIsolatedOperation
+ {
+ final List<NodeData> childs;
+
+ final NodeData parent;
+
+ CacheNodesInTransaction(NodeData parent, List<NodeData> childs)
+ {
+ this.parent = parent;
+ this.childs = childs;
+ }
+
+ @Override
+ protected void action() throws RepositoryException
+ {
+ cache.addChildNodes(parent, childs);
+ }
+ }
+
+ protected class CachePropertiesInTransaction extends StorageTxIsolatedOperation
+ {
+ final List<PropertyData> childs;
+
+ final NodeData parent;
+
+ CachePropertiesInTransaction(NodeData parent, List<PropertyData> childs)
+ {
+ this.parent = parent;
+ this.childs = childs;
+ }
+
+ @Override
+ protected void action() throws RepositoryException
+ {
+ cache.addChildProperties(parent, childs);
+ }
+ }
+
+ protected class CachePropertiesListInTransaction extends StorageTxIsolatedOperation
+ {
+ final List<PropertyData> childsList;
+
+ final NodeData parent;
+
+ CachePropertiesListInTransaction(NodeData parent, List<PropertyData> childsList)
+ {
+ this.parent = parent;
+ this.childsList = childsList;
+ }
+
+ @Override
+ protected void action() throws RepositoryException
+ {
+ cache.addChildPropertiesList(parent, childsList);
+ }
+ }
+
+ protected class CacheItemInTransaction extends StorageTxIsolatedOperation
+ {
+ final ItemData item;
+
+ CacheItemInTransaction(ItemData item)
+ {
+ this.item = item;
+ }
+
+ @Override
+ protected void action() throws RepositoryException
+ {
+ cache.put(item);
+ }
+ }
+
/**
* CacheableWorkspaceDataManager constructor.
*
@@ -302,7 +432,7 @@
transactionManager = null;
}
}
-
+
/**
* Get Items Cache.
*
@@ -343,7 +473,19 @@
*/
public List<PropertyData> getChildPropertiesData(NodeData nodeData) throws RepositoryException
{
- return getChildPropertiesData(nodeData, false);
+
+ List<PropertyData> childs = getChildPropertiesData(nodeData, false);
+ // for (int i = 0; i < childs.size(); i++)
+ // {
+ // PropertyData data = childs.get(i);
+ // if (data.getValues() == null)
+ // {
+ // // refill the property data if values invalid (null)
+ // childs.set(i, fillPropertyValue(data));
+ // }
+ // }
+
+ return childs;
}
/**
@@ -360,6 +502,11 @@
{
data = getPersistedItemData(parentData, name);
}
+ // else if (!data.isNode() && ((PropertyData)data).getValues() == null)
+ // {
+ // // refill the property data if values invalid (null)
+ // data = fillPropertyValue((PropertyData)data);
+ // }
return data;
}
@@ -377,6 +524,12 @@
{
return getPersistedItemData(identifier);
}
+ // else if (!data.isNode() && ((PropertyData)data).getValues() == null)
+ // {
+ // // refill the property data if values invalid (null)
+ // data = fillPropertyValue((PropertyData)data);
+ // }
+
return data;
}
@@ -403,226 +556,19 @@
@Override
public void save(final ItemStateChangesLog changesLog) throws RepositoryException
{
- if (transactionManager == null)
+ if (isTxAware())
{
- super.save(changesLog);
-
- // notify listeners after storage commit
- notifySaveItems(changesLog, false);
+ // save in dedicated XA transaction
+ new SaveInTransaction(changesLog).perform();
}
else
{
- try
- {
- // Care about dedicated XA transaction for storage save:
- // suspend current ransaction and create one new for the JCR storage (cache etc.)
- // after the new transaction done we'll resume the current.
- Transaction current = transactionManager.suspend();
- try
- {
- saveInTransaction(changesLog);
-
- // notify listeners after transaction commit but before the current resume!
- try
- {
- notifySaveItems(changesLog, false);
- }
- catch (Throwable th)
- {
- // TODO XA layer can throws runtime exceptions
- throw new RepositoryException(th);
- }
- }
- finally
- {
- if (current != null)
- {
- try
- {
- transactionManager.resume(current);
- }
- catch (InvalidTransactionException e)
- {
- throw new RepositoryException(e);
- }
- catch (IllegalStateException e)
- {
- throw new RepositoryException(e);
- }
- }
- }
- }
- catch (SystemException e)
- {
- throw new RepositoryException(e);
- }
-
- // TODO to do not commit in curr thread (i.e. curr tx)
- // try
- // {
- // if (transactionManager.getStatus() == Status.STATUS_COMMITTING)
- // {
- // // The JCR session has been enrolled into a XA Transaction, the method applyChanges must be called in another thread since the operations
- // // that we do into the cache are not allowed within the current Transaction, so to do it in another Transaction we need to call the method
- // // from another Thread
- // final AtomicReference<Exception> exception = new AtomicReference<Exception>();
- // final CountDownLatch doneSignal = new CountDownLatch(1);
- // Thread t = new Thread()
- // {
- // public void run()
- // {
- // try
- // {
- // applyChanges(changesLog);
- // }
- // catch (Exception e)
- // {
- // exception.set(e);
- // }
- // finally
- // {
- // doneSignal.countDown();
- // }
- // }
- // };
- // t.start();
- // doneSignal.await();
- // Exception e = exception.get();
- // if (e != null)
- // {
- // if (e instanceof RepositoryException)
- // {
- // throw (RepositoryException)e;
- // }
- // else
- // {
- // throw new RuntimeException(e);
- // }
- // }
- // }
- // else
- // {
- // // Normal Transaction
- // applyChanges(changesLog);
- // }
- // }
- // catch (RepositoryException e)
- // {
- // throw e;
- // }
- // catch (InterruptedException e)
- // {
- // throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
- // }
- // catch (SystemException e)
- // {
- // throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
- // }
- }
- }
-
- /**
- * Apply all the changes in new XA transaction. This save should run in dedicated XA transaction, i.e. only JCR storage stuff should be involved to.
- */
- private void saveInTransaction(ItemStateChangesLog changesLog) throws RepositoryException
- {
- try
- {
- transactionManager.begin(); // start new global tx
- cache.beginTransaction(); // TODO keep it into the cache impl
+ // save normaly
super.save(changesLog);
- cache.commitTransaction();
- transactionManager.commit(); // commit global tx
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (JCRInvalidItemStateException e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback(); // rollback global tx
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
- throw new JCRInvalidItemStateException(e.getMessage(), e.getIdentifier(), e.getState(), e);
+ // notify listeners after storage commit
+ notifySaveItems(changesLog, false);
}
- catch (InvalidItemStateException e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new InvalidItemStateException(e);
- }
- catch (ItemExistsException e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new ItemExistsException(e);
- }
- catch (ReadOnlyWorkspaceException e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new ReadOnlyWorkspaceException(e);
- }
- catch (RepositoryException e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
}
/**
@@ -697,47 +643,49 @@
if (parentData != null)
{
- if (transactionManager == null)
+ if (isTxAware())
{
- cache.addChildNodes(parentData, childNodes);
+ new CacheNodesInTransaction(parentData, childNodes).perform();
+
+ // TODO
+ // try
+ // {
+ // if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
+ // {
+ // cache.addChildNodes(parentData, childNodes);
+ // }
+ // else
+ // {
+ // transactionManager.begin();
+ // cache.beginTransaction();
+ // cache.addChildNodes(parentData, childNodes);
+ // cache.commitTransaction();
+ // transactionManager.commit();
+ // }
+ // }
+ // catch (RollbackException e)
+ // {
+ // // Indicate that the transaction has been rolled back rather than committed.
+ // throw new RepositoryException(e);
+ // }
+ // catch (Exception e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
}
else
{
-
- try
- {
- if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
- {
- cache.addChildNodes(parentData, childNodes);
- }
- else
- {
- transactionManager.begin();
- cache.beginTransaction();
- cache.addChildNodes(parentData, childNodes);
- cache.commitTransaction();
- transactionManager.commit();
- }
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
+ cache.addChildNodes(parentData, childNodes);
}
}
}
@@ -793,46 +741,49 @@
if (parentData != null)
{
- if (transactionManager == null)
+ if (isTxAware())
{
- cache.addChildProperties(parentData, childProperties);
+ new CachePropertiesInTransaction(parentData, childProperties).perform();
+
+ // TODO
+ // try
+ // {
+ // if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
+ // {
+ // cache.addChildProperties(parentData, childProperties);
+ // }
+ // else
+ // {
+ // transactionManager.begin();
+ // cache.beginTransaction();
+ // cache.addChildProperties(parentData, childProperties);
+ // cache.commitTransaction();
+ // transactionManager.commit();
+ // }
+ // }
+ // catch (RollbackException e)
+ // {
+ // // Indicate that the transaction has been rolled back rather than committed.
+ // throw new RepositoryException(e);
+ // }
+ // catch (Exception e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
}
else
{
- try
- {
- if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
- {
- cache.addChildProperties(parentData, childProperties);
- }
- else
- {
- transactionManager.begin();
- cache.beginTransaction();
- cache.addChildProperties(parentData, childProperties);
- cache.commitTransaction();
- transactionManager.commit();
- }
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
+ cache.addChildProperties(parentData, childProperties);
}
}
}
@@ -857,51 +808,52 @@
*/
protected ItemData getPersistedItemData(NodeData parentData, QPathEntry name) throws RepositoryException
{
-
- ItemData data = null;
- data = super.getItemData(parentData, name);
+ ItemData data = super.getItemData(parentData, name);
if (data != null && cache.isEnabled())
{
- if (transactionManager == null)
+ if (isTxAware())
{
- cache.put(data);
+ new CacheItemInTransaction(data).perform();
+
+ // TODO
+ // try
+ // {
+ // if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
+ // {
+ // cache.put(data);
+ // }
+ // else
+ // {
+ // transactionManager.begin();
+ // cache.beginTransaction();
+ // cache.put(data);
+ // cache.commitTransaction();
+ // transactionManager.commit();
+ // }
+ // }
+ // catch (RollbackException e)
+ // {
+ // // Indicate that the transaction has been rolled back rather than committed.
+ // throw new RepositoryException(e);
+ // }
+ // catch (Exception e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
}
else
{
- try
- {
- if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
- {
- cache.put(data);
- }
- else
- {
- transactionManager.begin();
- cache.beginTransaction();
- cache.put(data);
- cache.commitTransaction();
- transactionManager.commit();
- }
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
+ cache.put(data);
}
}
return data;
@@ -919,46 +871,49 @@
ItemData data = super.getItemData(identifier);
if (data != null && cache.isEnabled())
{
- if (transactionManager == null)
+ if (isTxAware())
{
- cache.put(data);
+ new CacheItemInTransaction(data).perform();
+
+ // TODO
+ // try
+ // {
+ // if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
+ // {
+ // cache.put(data);
+ // }
+ // else
+ // {
+ // transactionManager.begin();
+ // cache.beginTransaction();
+ // cache.put(data);
+ // cache.commitTransaction();
+ // transactionManager.commit();
+ // }
+ // }
+ // catch (RollbackException e)
+ // {
+ // // Indicate that the transaction has been rolled back rather than committed.
+ // throw new RepositoryException(e);
+ // }
+ // catch (Exception e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
}
else
{
- try
- {
- if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
- {
- cache.put(data);
- }
- else
- {
- transactionManager.begin();
- cache.beginTransaction();
- cache.put(data);
- cache.commitTransaction();
- transactionManager.commit();
- }
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
+ cache.put(data);
}
}
return data;
@@ -1004,49 +959,185 @@
if (parentData != null)
{
- if (transactionManager == null)
+ if (isTxAware())
{
- cache.addChildPropertiesList(parentData, propertiesList);
+ new CachePropertiesListInTransaction(parentData, propertiesList).perform();
+
+ // if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
+ // {
+ // cache.addChildPropertiesList(parentData, propertiesList);
+ // }
+ // else
+ // {
+ // try
+ // {
+ // transactionManager.begin();
+ // cache.beginTransaction();
+ // cache.addChildPropertiesList(parentData, propertiesList);
+ // cache.commitTransaction();
+ // transactionManager.commit();
+ // }
+ // catch (RollbackException e)
+ // {
+ // // Indicate that the transaction has been rolled back rather than committed.
+ // throw new RepositoryException(e);
+ // }
+ // catch (Exception e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
+ // }
}
else
{
- try
- {
- if (transactionManager.getStatus() == Status.STATUS_ACTIVE)
- {
- cache.addChildPropertiesList(parentData, propertiesList);
- }
- else
- {
- transactionManager.begin();
- cache.beginTransaction();
- cache.addChildPropertiesList(parentData, propertiesList);
- cache.commitTransaction();
- transactionManager.commit();
- }
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
- {
- cache.rollbackTransaction();
- transactionManager.rollback();
- }
- catch (Exception e1)
- {
- LOG.error("Rollback error ", e1);
- }
-
- throw new RepositoryException(e);
- }
+ cache.addChildPropertiesList(parentData, propertiesList);
}
}
}
return propertiesList;
}
+
+ // /**
+ // * Apply all the changes in new XA transaction. This save should run in dedicated XA transaction,
+ // * i.e. only JCR storage stuff should be involved to.
+ // */
+ // private void saveInTransaction(ItemStateChangesLog changes) throws RepositoryException
+ // {
+ // try
+ // {
+ // transactionManager.begin(); // start new global tx
+ // cache.beginTransaction(); // TODO keep it into the cache impl
+ // CacheableWorkspaceDataManager.super.save(changes);
+ // cache.commitTransaction();
+ // transactionManager.commit(); // commit global tx
+ // }
+ // catch (RollbackException e)
+ // {
+ // // Indicate that the transaction has been rolled back rather than committed.
+ // throw new RepositoryException(e);
+ // }
+ // catch (JCRInvalidItemStateException e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback(); // rollback global tx
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new JCRInvalidItemStateException(e.getMessage(), e.getIdentifier(), e.getState(), e);
+ // }
+ // catch (InvalidItemStateException e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new InvalidItemStateException(e);
+ // }
+ // catch (ItemExistsException e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new ItemExistsException(e);
+ // }
+ // catch (ReadOnlyWorkspaceException e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new ReadOnlyWorkspaceException(e);
+ // }
+ // catch (RepositoryException e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
+ // catch (Exception e)
+ // {
+ // try
+ // {
+ // cache.rollbackTransaction();
+ // transactionManager.rollback();
+ // }
+ // catch (Exception e1)
+ // {
+ // LOG.error("Rollback error ", e1);
+ // }
+ //
+ // throw new RepositoryException(e);
+ // }
+ // }
+
+ protected boolean isTxAware()
+ {
+ return transactionManager != null;
+ }
+
+ // /**
+ // * Fill Property Value from persistent storage.
+ // *
+ // * @param prop PropertyData, original Property data
+ // * @return PropertyData
+ // * @throws IllegalStateException
+ // * @throws RepositoryException
+ // */
+ // protected PropertyData fillPropertyValue(PropertyData prop) throws IllegalStateException, RepositoryException
+ // {
+ // // TODO use interface not JDBC
+ // JDBCStorageConnection conn = (JDBCStorageConnection)dataContainer.openConnection();
+ // try
+ // {
+ // return new PersistedPropertyData(prop.getIdentifier(), prop.getQPath(), prop.getParentIdentifier(), prop
+ // .getPersistedVersion(), prop.getType(), prop.isMultiValued(), conn.getPropertyValues(prop.getIdentifier(),
+ // prop.getPersistedVersion()));
+ // }
+ // finally
+ // {
+ // conn.close();
+ // }
+ // }
}
Property changes on: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
___________________________________________________________________
Name: svn:keywords
+ Id
Added: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java
===================================================================
--- jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java (rev 0)
+++ jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java 2010-01-17 08:19:24 UTC (rev 1440)
@@ -0,0 +1,264 @@
+package org.exoplatform.services.jcr.impl.dataflow.persistent;
+
+import org.exoplatform.services.jcr.impl.storage.JCRInvalidItemStateException;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * Handles XA transactionalyisolated operation. I.e. Action of this operation will be executed in dedicated global transaction.
+ * If another current transaction exists, the one will be suspended and resumed after the execution.
+ * At other hand if nested isolated operations perform they will use same (current, active) transaction.
+ */
+public abstract class TxIsolatedOperation
+{
+ protected static final Log LOG = ExoLogger.getLogger("jcr.TxIsolatedOperation");
+
+ protected final TransactionManager txManager;
+
+ protected final static ThreadLocal<Transaction> currentIsolated = new ThreadLocal<Transaction>();
+
+ public TxIsolatedOperation(TransactionManager txManager)
+ {
+ this.txManager = txManager;
+ }
+
+ /**
+ * Action body for a final implementation.
+ *
+ * @throws RepositoryException
+ */
+ protected abstract void action() throws RepositoryException;
+
+ protected void beginTx() throws NotSupportedException, SystemException
+ {
+ txManager.begin(); // start new global tx
+ }
+
+ protected void commitTx() throws SecurityException, IllegalStateException, RollbackException,
+ HeuristicMixedException, HeuristicRollbackException, SystemException
+ {
+ txManager.commit(); // commit global tx
+ }
+
+ protected void rollbackTx() throws NotSupportedException, SystemException
+ {
+ txManager.rollback(); // rollback global tx
+ }
+
+ /**
+ * Apply action in new XA transaction (begin then commit or rollback).
+ * Action will runs in dedicated (isolated) XA transaction, i.e. only JCR storage stuff will be involved to.
+ * But if it's a nested isolated operation it will run the action assuming the same (current, active) transaction.
+ */
+ protected void txAction() throws RepositoryException
+ {
+ final boolean actInTx = currentIsolated.get() == null;
+ try
+ {
+ if (actInTx)
+ {
+ beginTx();
+
+ // remember current isolated transaction for this thread
+ Transaction current = txManager.getTransaction();
+ if (current != null)
+ {
+ currentIsolated.set(current);
+ }
+ }
+
+ action();
+
+ if (actInTx)
+ {
+ commitTx();
+
+ // remove current isolated transaction from this thread
+ currentIsolated.remove();
+ }
+ }
+ catch (RollbackException e)
+ {
+ if (actInTx)
+ {
+ // remove current isolated transaction from this thread
+ currentIsolated.remove();
+ }
+ // Indicate that the transaction has been rolled back rather than committed.
+ throw new RepositoryException(e);
+ }
+ catch (JCRInvalidItemStateException e)
+ {
+ doRollback(actInTx);
+ throw new JCRInvalidItemStateException(e.getMessage(), e.getIdentifier(), e.getState(), e);
+ }
+ catch (InvalidItemStateException e)
+ {
+ doRollback(actInTx);
+ throw new InvalidItemStateException(e);
+ }
+ catch (ItemExistsException e)
+ {
+ doRollback(actInTx);
+ throw new ItemExistsException(e);
+ }
+ catch (ReadOnlyWorkspaceException e)
+ {
+ doRollback(actInTx);
+ throw new ReadOnlyWorkspaceException(e);
+ }
+ catch (RepositoryException e)
+ {
+ doRollback(actInTx);
+ throw new RepositoryException(e);
+ }
+ catch (Exception e)
+ {
+ doRollback(actInTx);
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * Performs rollback of the action if it's acts in original isolated transaction.
+ * If it's acts as a nested operation, the actions will be commited in original (rooted) isolated trnsaction.
+ *
+ * @param actInTx boolean, true if it's original isolated transaction
+ */
+ private void doRollback(boolean actInTx)
+ {
+ if (actInTx)
+ {
+ try
+ {
+ rollbackTx();
+ }
+ catch (Exception e1)
+ {
+ LOG.error("Rollback error ", e1);
+ }
+ // remove current isolated transaction from this thread
+ currentIsolated.remove();
+ }
+ }
+
+ /**
+ * Apply the action in new XA transaction. Action should run in dedicated XA transaction,
+ * i.e. only JCR storage stuff should be involved to.
+ */
+ public void perform() throws RepositoryException
+ {
+ try
+ {
+ // Care about dedicated XA transaction for storage save:
+ // suspend current ransaction and create one new for the JCR storage (cache etc.)
+ // after the new transaction done we'll resume the current.
+
+ // TODO if nested in storage, e.g. save causes read, use one tx, e.g. via ThreadLocal
+ //if (txManager.getStatus() == Status.STATUS_ACTIVE)
+
+ Transaction current = txManager.suspend();
+ try
+ {
+ txAction();
+ }
+ finally
+ {
+ if (current != null)
+ {
+ try
+ {
+ txManager.resume(current);
+ }
+ catch (InvalidTransactionException e)
+ {
+ throw new RepositoryException(e);
+ }
+ catch (IllegalStateException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+ }
+ }
+ catch (SystemException e)
+ {
+ throw new RepositoryException(e);
+ }
+
+ // TODO to do not commit in curr thread (i.e. curr tx)
+ // try
+ // {
+ // if (transactionManager.getStatus() == Status.STATUS_COMMITTING)
+ // {
+ // // The JCR session has been enrolled into a XA Transaction, the method applyChanges must be called in another thread since the operations
+ // // that we do into the cache are not allowed within the current Transaction, so to do it in another Transaction we need to call the method
+ // // from another Thread
+ // final AtomicReference<Exception> exception = new AtomicReference<Exception>();
+ // final CountDownLatch doneSignal = new CountDownLatch(1);
+ // Thread t = new Thread()
+ // {
+ // public void run()
+ // {
+ // try
+ // {
+ // applyChanges(changesLog);
+ // }
+ // catch (Exception e)
+ // {
+ // exception.set(e);
+ // }
+ // finally
+ // {
+ // doneSignal.countDown();
+ // }
+ // }
+ // };
+ // t.start();
+ // doneSignal.await();
+ // Exception e = exception.get();
+ // if (e != null)
+ // {
+ // if (e instanceof RepositoryException)
+ // {
+ // throw (RepositoryException)e;
+ // }
+ // else
+ // {
+ // throw new RuntimeException(e);
+ // }
+ // }
+ // }
+ // else
+ // {
+ // // Normal Transaction
+ // applyChanges(changesLog);
+ // }
+ // }
+ // catch (RepositoryException e)
+ // {
+ // throw e;
+ // }
+ // catch (InterruptedException e)
+ // {
+ // throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
+ // }
+ // catch (SystemException e)
+ // {
+ // throw new RepositoryException(e.getLocalizedMessage(), e.getCause());
+ // }
+ }
+}
Property changes on: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/TxIsolatedOperation.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Id
Modified: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java
===================================================================
--- jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2010-01-17 08:09:07 UTC (rev 1439)
+++ jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/WorkspacePersistentDataManager.java 2010-01-17 08:19:24 UTC (rev 1440)
@@ -41,8 +41,11 @@
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
+import org.exoplatform.services.jcr.impl.storage.value.fs.FileIOChannel;
import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
+import org.exoplatform.services.jcr.storage.value.ValueIOChannel;
+import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
@@ -56,6 +59,7 @@
import java.util.Set;
import javax.jcr.InvalidItemStateException;
+import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
/**
@@ -77,14 +81,19 @@
/**
* Workspace data container (persistent storage).
*/
- protected WorkspaceDataContainer dataContainer;
+ protected final WorkspaceDataContainer dataContainer;
/**
* System workspace data container (persistent storage).
*/
- protected WorkspaceDataContainer systemDataContainer;
+ protected final WorkspaceDataContainer systemDataContainer;
/**
+ * Value sorages provider (for dest file suggestion on save).
+ */
+ // TODO protected final ValueStoragePluginProvider valueStorageProvider;
+
+ /**
* Persistent level listeners. This listeners can be filtered by filters from
* <code>liestenerFilters</code> list.
*/
@@ -114,13 +123,16 @@
* holder of system workspace data container
*/
public WorkspacePersistentDataManager(WorkspaceDataContainer dataContainer,
+ //ValueStoragePluginProvider valueStorageProvider,
SystemDataContainerHolder systemDataContainerHolder)
{
this.dataContainer = dataContainer;
+ this.systemDataContainer = systemDataContainerHolder.getContainer();
+ // this.valueStorageProvider = valueStorageProvider;
+
this.listeners = new ArrayList<ItemsPersistenceListener>();
this.mandatoryListeners = new ArrayList<MandatoryItemsPersistenceListener>();
this.liestenerFilters = new ArrayList<ItemsPersistenceListenerFilter>();
- this.systemDataContainer = systemDataContainerHolder.getContainer();
}
/**
@@ -128,18 +140,6 @@
*/
public void save(final ItemStateChangesLog changesLog) throws RepositoryException
{
- doSave(changesLog);
- }
-
- /**
- * Save the list of changes to storage.
- *
- * @param changesLog
- * @throws RepositoryException
- */
- private void doSave(final ItemStateChangesLog changesLog) throws RepositoryException
- {
- //LOG.info(changesLog.dump())
// check if this workspace container is not read-only
if (readOnly && !(changesLog instanceof ReadOnlyThroughChanges))
{
@@ -234,7 +234,7 @@
// if it's different container instances
? systemDataContainer.equals(dataContainer) && thisConnection != null
// but container confugrations are same and non-system connnection open
- // reuse this connection as system
+ // reuse this connection as system
? systemDataContainer.reuseConnection(thisConnection)
// or open one new system
: systemDataContainer.openConnection()
@@ -256,7 +256,7 @@
// if it's different container instances
? dataContainer.equals(systemDataContainer) && systemConnection != null
// but container confugrations are same and system connnection open
- // reuse system connection as this
+ // reuse system connection as this
? dataContainer.reuseConnection(systemConnection)
// or open one new
: dataContainer.openConnection()
@@ -273,7 +273,7 @@
protected PlainChangesLogImpl save(PlainChangesLog changesLog) throws InvalidItemStateException,
RepositoryException, IOException
{ //LOG.info(changesLog.dump())
- // copy state
+ // copy state
PlainChangesLogImpl newLog =
new PlainChangesLogImpl(new ArrayList<ItemState>(), changesLog.getSessionId(), changesLog.getEventType(),
changesLog.getPairId());
@@ -303,7 +303,7 @@
{
PropertyData prevData = (PropertyData)prevState.getData();
- if (prevData.getValues() != null)
+ if (prevData.getValues() != null) // null if it's DELETE state
{
List<ValueData> values = new ArrayList<ValueData>();
for (int i = 0; i < prevData.getValues().size(); i++)
@@ -326,16 +326,15 @@
// TODO for JBC case, the storage connection will evict the replicated Value to read it from the DB
File destFile = null;
- // TODO review TransientValueData logic about spool file and stream
if (tvd.getSpoolFile() != null)
{
// spooled to temp file
- pvd = new StreamPersistedValueData(i, tvd.getSpoolFile());
+ pvd = new StreamPersistedValueData(i, tvd.getSpoolFile(), destFile);
}
else
{
// with original stream
- pvd = new StreamPersistedValueData(i, tvd.getOriginalStream());
+ pvd = new StreamPersistedValueData(i, tvd.getOriginalStream(), destFile);
}
values.add(pvd);
@@ -397,7 +396,7 @@
}
else if (itemState.isDeleted())
{
- doDelete(data, conn);
+ doDelete(data, conn);
}
else if (itemState.isRenamed())
{
@@ -759,13 +758,17 @@
for (MandatoryItemsPersistenceListener mlistener : mandatoryListeners)
{
if (mlistener.isTXAware() == isListenerTXAware)
+ {
mlistener.onSaveItems(changesLog);
+ }
}
for (ItemsPersistenceListener listener : listeners)
{
if (listener.isTXAware() == isListenerTXAware && isListenerAccepted(listener))
+ {
listener.onSaveItems(changesLog);
+ }
}
}
Modified: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
--- jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2010-01-17 08:09:07 UTC (rev 1439)
+++ jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java 2010-01-17 08:19:24 UTC (rev 1440)
@@ -58,7 +58,7 @@
*/
private final Cache<Serializable, Object> parentCache;
- private ThreadLocal<CompressedChangesBuffer> changesList = new ThreadLocal<CompressedChangesBuffer>();
+ private final ThreadLocal<CompressedChangesBuffer> changesList = new ThreadLocal<CompressedChangesBuffer>();
private ThreadLocal<Boolean> local = new ThreadLocal<Boolean>();
@@ -100,6 +100,7 @@
finally
{
changesList.set(null);
+ changesContainer = null;
}
}
Modified: jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
--- jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2010-01-17 08:09:07 UTC (rev 1439)
+++ jcr/branches/1.12.0-JBCCACHE/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2010-01-17 08:19:24 UTC (rev 1440)
@@ -33,6 +33,7 @@
import org.exoplatform.services.jcr.impl.Constants;
import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import org.exoplatform.services.jcr.impl.dataflow.persistent.TxIsolatedOperation;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.transaction.TransactionService;
@@ -306,42 +307,23 @@
protected void prepareCache() throws RepositoryException
{
-
TransactionManager txm = cache.getTransactionManager();
- try
+ final Node<Serializable, Object> cacheRoot = cache.getRoot();
+ TxIsolatedOperation prepare = new TxIsolatedOperation(txm)
{
- txm.begin();
-
- Node<Serializable, Object> cacheRoot = cache.getRoot();
-
- cacheRoot.addChild(this.itemsRoot).setResident(true);
- cacheRoot.addChild(this.childNodes).setResident(true);
- cacheRoot.addChild(this.childNodesList).setResident(true);
- cacheRoot.addChild(this.childProps).setResident(true);
- cacheRoot.addChild(this.childPropsList).setResident(true);
- cacheRoot.addChild(refsRoot).setResident(true);
-
- txm.commit();
- }
- catch (RollbackException e)
- {
- // Indicate that the transaction has been rolled back rather than committed.
- throw new RepositoryException(e);
- }
- catch (Exception e)
- {
- try
+ @Override
+ protected void action() throws RepositoryException
{
- txm.rollback();
- throw new RepositoryException("Cannot preare cache", e);
+ cacheRoot.addChild(itemsRoot).setResident(true);
+ cacheRoot.addChild(childNodes).setResident(true);
+ cacheRoot.addChild(childNodesList).setResident(true);
+ cacheRoot.addChild(childProps).setResident(true);
+ cacheRoot.addChild(childPropsList).setResident(true);
+ cacheRoot.addChild(refsRoot).setResident(true);
}
- catch (Exception e1)
- {
- LOG.error("Error of rolback ", e1);
- }
+ };
- throw new RepositoryException(e);
- }
+ prepare.perform();
}
protected static String readJBCConfig(final WorkspaceEntry wsConfig) throws RepositoryConfigurationException
More information about the exo-jcr-commits
mailing list