[exo-jcr-commits] exo-jcr SVN: r4238 - jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604.
do-not-reply at jboss.org
do-not-reply at jboss.org
Fri Apr 15 09:26:15 EDT 2011
Author: sergiykarpenko
Date: 2011-04-15 09:26:15 -0400 (Fri, 15 Apr 2011)
New Revision: 4238
Modified:
jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/JCR-1604.patch
Log:
JCR-1604: new patch proposed
Modified: jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/JCR-1604.patch
===================================================================
--- jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/JCR-1604.patch 2011-04-14 14:09:41 UTC (rev 4237)
+++ jcr/branches/1.12.x/patch/1.12.9-GA/JCR-1604/JCR-1604.patch 2011-04-15 13:26:15 UTC (rev 4238)
@@ -1,8 +1,780 @@
+Index: exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java
+===================================================================
+--- exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java (revision 0)
++++ exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/TestJBossCacheWorkspaceStorageCacheInClusterMode.java (revision 0)
+@@ -0,0 +1,648 @@
++/*
++ * Copyright (C) 2011 eXo Platform SAS.
++ *
++ * This is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU Lesser General Public License as
++ * published by the Free Software Foundation; either version 2.1 of
++ * the License, or (at your option) any later version.
++ *
++ * This software is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this software; if not, write to the Free
++ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
++ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
++ */
++package org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache;
++
++import org.exoplatform.container.configuration.ConfigurationManagerImpl;
++import org.exoplatform.services.jcr.JcrImplBaseTest;
++import org.exoplatform.services.jcr.config.CacheEntry;
++import org.exoplatform.services.jcr.config.SimpleParameterEntry;
++import org.exoplatform.services.jcr.config.WorkspaceEntry;
++import org.exoplatform.services.jcr.dataflow.ItemState;
++import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
++import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
++import org.exoplatform.services.jcr.dataflow.persistent.PersistedNodeData;
++import org.exoplatform.services.jcr.dataflow.persistent.PersistedPropertyData;
++import org.exoplatform.services.jcr.datamodel.InternalQName;
++import org.exoplatform.services.jcr.datamodel.ItemData;
++import org.exoplatform.services.jcr.datamodel.ItemType;
++import org.exoplatform.services.jcr.datamodel.NodeData;
++import org.exoplatform.services.jcr.datamodel.PropertyData;
++import org.exoplatform.services.jcr.datamodel.QPath;
++import org.exoplatform.services.jcr.datamodel.QPathEntry;
++import org.exoplatform.services.jcr.datamodel.ValueData;
++import org.exoplatform.services.jcr.impl.Constants;
++import org.exoplatform.services.jcr.impl.dataflow.persistent.ByteArrayPersistedValueData;
++import org.exoplatform.services.jcr.impl.dataflow.persistent.CacheableWorkspaceDataManager;
++import org.exoplatform.services.jcr.impl.storage.SystemDataContainerHolder;
++import org.exoplatform.services.jcr.impl.storage.WorkspaceDataContainerBase;
++import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
++import org.exoplatform.services.jcr.storage.WorkspaceStorageConnection;
++import org.exoplatform.services.transaction.TransactionService;
++
++import java.io.UnsupportedEncodingException;
++import java.util.ArrayList;
++import java.util.Arrays;
++import java.util.List;
++import java.util.concurrent.CountDownLatch;
++import java.util.concurrent.atomic.AtomicReference;
++
++import javax.jcr.InvalidItemStateException;
++import javax.jcr.PropertyType;
++import javax.jcr.RepositoryException;
++
++/**
++ * @author <a href="mailto:nicolas.filotto at exoplatform.com">Nicolas Filotto</a>
++ * @version $Id$
++ */
++public class TestJBossCacheWorkspaceStorageCacheInClusterMode extends JcrImplBaseTest
++{
++
++ public JBossCacheWorkspaceStorageCache getCacheImpl() throws Exception
++ {
++ TransactionService transactionService =
++ (TransactionService)container.getComponentInstanceOfType(TransactionService.class);
++
++ ArrayList<SimpleParameterEntry> list = new ArrayList<SimpleParameterEntry>();
++ list.add(new SimpleParameterEntry(JBossCacheWorkspaceStorageCache.JBOSSCACHE_CONFIG,
++ "jar:/conf/standalone/cluster/test-jbosscache-data-no-mux.xml"));
++ list.add(new SimpleParameterEntry("jbosscache-cluster-name", "TestJBossCacheWorkspaceStorageCacheInClusterMode"));
++
++ CacheEntry entry = new CacheEntry(list);
++ WorkspaceEntry workspaceEntry = new WorkspaceEntry();
++ workspaceEntry.setCache(entry);
++ return new JBossCacheWorkspaceStorageCache(workspaceEntry,
++ transactionService == null ? null : transactionService, new ConfigurationManagerImpl());
++ }
++
++ public void testRaceConditions() throws Exception
++ {
++ JBossCacheWorkspaceStorageCache cache1 = null, cache2 = null;
++ try
++ {
++ MyWorkspaceStorageConnection con = new MyWorkspaceStorageConnection();
++ WorkspaceDataContainer wdc = new MyWorkspaceDataContainer(con);
++ CacheableWorkspaceDataManager cwdmNode1 =
++ new CacheableWorkspaceDataManager(wdc, cache1 = getCacheImpl(), new SystemDataContainerHolder(wdc));
++ CacheableWorkspaceDataManager cwdmNode2 =
++ new CacheableWorkspaceDataManager(wdc, cache2 = getCacheImpl(), new SystemDataContainerHolder(wdc));
++ NodeData parentNode = new PersistedNodeData("parent-id", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ // Test getChildNodesData
++ Action readAction = new Action(cwdmNode2)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ cwdm.getChildNodesData(parentNode);
++ }
++ };
++ Action writeAction = new Action(cwdmNode1)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ PlainChangesLog chlog = new PlainChangesLogImpl();
++ cwdm.getChildNodesData(parentNode);
++ chlog.add(ItemState.createAddedState(new PersistedNodeData("id-node" + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), new InternalQName(null, "node")), parentNode.getIdentifier(), 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null)));
++ cwdm.save(chlog);
++ }
++ };
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getChildNodesData(parentNode));
++ assertEquals(2, cwdmNode1.getChildNodesData(parentNode).size());
++ assertNotNull(cwdmNode2.getChildNodesData(parentNode));
++ assertEquals(2, cwdmNode2.getChildNodesData(parentNode).size());
++ parentNode = new PersistedNodeData("parent-id2", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node2")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getChildNodesData(parentNode));
++ assertEquals(2, cwdmNode1.getChildNodesData(parentNode).size());
++ assertNotNull(cwdmNode2.getChildNodesData(parentNode));
++ assertEquals(2, cwdmNode2.getChildNodesData(parentNode).size());
++ // Test getChildPropertiesData
++ readAction = new Action(cwdmNode2)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ cwdm.getChildPropertiesData(parentNode);
++ }
++ };
++ writeAction = new Action(cwdmNode1)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ PlainChangesLog chlog = new PlainChangesLogImpl();
++ cwdm.getChildPropertiesData(parentNode);
++ chlog.add(ItemState.createAddedState(new PersistedPropertyData("id-property" + parentNode.getIdentifier(), QPath.makeChildPath(
++ parentNode.getQPath(), new InternalQName(null, "property")), parentNode.getIdentifier(), 0,
++ PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, "some data".getBytes("UTF-8"))))));
++ cwdm.save(chlog);
++ }
++ };
++ parentNode = new PersistedNodeData("parent-id3", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node3")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getChildPropertiesData(parentNode));
++ assertEquals(2, cwdmNode1.getChildPropertiesData(parentNode).size());
++ assertNotNull(cwdmNode2.getChildPropertiesData(parentNode));
++ assertEquals(2, cwdmNode2.getChildPropertiesData(parentNode).size());
++ parentNode = new PersistedNodeData("parent-id4", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node4")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getChildPropertiesData(parentNode));
++ assertEquals(2, cwdmNode1.getChildPropertiesData(parentNode).size());
++ assertNotNull(cwdmNode2.getChildPropertiesData(parentNode));
++ assertEquals(2, cwdmNode2.getChildPropertiesData(parentNode).size());
++ // Test getReferencesData
++ readAction = new Action(cwdmNode2)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ cwdm.getReferencesData(parentNode.getIdentifier(), false);
++ }
++ };
++ writeAction = new Action(cwdmNode1)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ PlainChangesLog chlog = new PlainChangesLogImpl();
++ cwdm.getReferencesData(parentNode.getIdentifier(), false);
++ chlog.add(ItemState.createAddedState(new PersistedPropertyData("id-reference" + parentNode.getIdentifier(), QPath.makeChildPath(
++ parentNode.getQPath(), new InternalQName(null, "reference")), parentNode.getIdentifier(), 0,
++ PropertyType.REFERENCE, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, parentNode.getIdentifier().getBytes("UTF-8"))))));
++ cwdm.save(chlog);
++ }
++ };
++ parentNode = new PersistedNodeData("parent-id5", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node5")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getReferencesData(parentNode.getIdentifier(), false));
++ assertEquals(2, cwdmNode1.getReferencesData(parentNode.getIdentifier(), false).size());
++ assertNotNull(cwdmNode2.getReferencesData(parentNode.getIdentifier(), false));
++ assertEquals(2, cwdmNode2.getReferencesData(parentNode.getIdentifier(), false).size());
++ parentNode = new PersistedNodeData("parent-id6", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node6")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getReferencesData(parentNode.getIdentifier(), false));
++ assertEquals(2, cwdmNode1.getReferencesData(parentNode.getIdentifier(), false).size());
++ assertNotNull(cwdmNode2.getReferencesData(parentNode.getIdentifier(), false));
++ assertEquals(2, cwdmNode2.getReferencesData(parentNode.getIdentifier(), false).size());
++
++ // Test getItemData by Id
++ readAction = new Action(cwdmNode2)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ cwdm.getItemData(parentNode.getIdentifier());
++ }
++ };
++ writeAction = new Action(cwdmNode1)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ PlainChangesLog chlog = new PlainChangesLogImpl();
++ cwdm.getItemData(parentNode.getIdentifier());
++ chlog.add(ItemState.createUpdatedState(new PersistedNodeData(parentNode.getIdentifier(), parentNode.getQPath(), Constants.ROOT_UUID, 2, 1,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null)));
++ cwdm.save(chlog);
++ }
++ };
++ parentNode = new PersistedNodeData("parent-id7", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node7")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getItemData(parentNode.getIdentifier()));
++ assertEquals(2, cwdmNode1.getItemData(parentNode.getIdentifier()).getPersistedVersion());
++ assertNotNull(cwdmNode2.getItemData(parentNode.getIdentifier()));
++ assertEquals(2, cwdmNode2.getItemData(parentNode.getIdentifier()).getPersistedVersion());
++ parentNode = new PersistedNodeData("parent-id8", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node8")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getItemData(parentNode.getIdentifier()));
++ assertEquals(2, cwdmNode1.getItemData(parentNode.getIdentifier()).getPersistedVersion());
++ assertNotNull(cwdmNode2.getItemData(parentNode.getIdentifier()));
++ assertEquals(2, cwdmNode2.getItemData(parentNode.getIdentifier()).getPersistedVersion());
++
++ // Test getItemData by Path
++ final QPathEntry qpe = new QPathEntry(null, "my-property", 1);
++ readAction = new Action(cwdmNode2)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ cwdm.getItemData(parentNode, qpe, ItemType.PROPERTY);
++ }
++ };
++ writeAction = new Action(cwdmNode1)
++ {
++ public void execute(NodeData parentNode) throws Exception
++ {
++ PlainChangesLog chlog = new PlainChangesLogImpl();
++ cwdm.getItemData(parentNode, qpe, ItemType.PROPERTY);
++ chlog.add(ItemState.createUpdatedState(new PersistedPropertyData("property-by-path"
++ + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), qpe), parentNode
++ .getIdentifier(), 2, PropertyType.STRING, false, Arrays
++ .asList((ValueData)new ByteArrayPersistedValueData(0, "some new data".getBytes("UTF-8"))))));
++ cwdm.save(chlog);
++ }
++ };
++ parentNode = new PersistedNodeData("parent-id9", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node9")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.READ_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY));
++ assertEquals(2, cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
++ assertNotNull(cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY));
++ assertEquals(2, cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
++ parentNode = new PersistedNodeData("parent-id10", QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName(null, "parent-node10")), Constants.ROOT_UUID, 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ executeConcurrentReadNWrite(con, readAction, writeAction, Mode.WRITE_FIRST, parentNode);
++ assertNotNull(cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY));
++ assertEquals(2, cwdmNode1.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
++ assertNotNull(cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY));
++ assertEquals(2, cwdmNode2.getItemData(parentNode, qpe, ItemType.PROPERTY).getPersistedVersion());
++ }
++ finally
++ {
++ if (cache1 != null)
++ {
++ try
++ {
++ cache1.cache.stop();
++ }
++ catch (Exception e)
++ {
++ // ignore me
++ }
++ }
++ if (cache2 != null)
++ {
++ try
++ {
++ cache2.cache.stop();
++ }
++ catch (Exception e)
++ {
++ // ignore me
++ }
++ }
++ }
++ }
++
++ /**
++ * @param con
++ * @param cwdm
++ * @param mode
++ * @param idNode
++ * @throws InterruptedException
++ */
++ private void executeConcurrentReadNWrite(final MyWorkspaceStorageConnection con, final Action readAction,
++ final Action writeAction, final Mode mode, final NodeData parentNode) throws InterruptedException
++ {
++ final CountDownLatch goSignal = con.initCountDownLatch();
++ con.setParentNode(parentNode);
++ final AtomicReference<Exception> ex = new AtomicReference<Exception>();
++ final CountDownLatch startSignal = new CountDownLatch(1);
++ final CountDownLatch doneSignal = new CountDownLatch(2);
++ Thread writer = new Thread()
++ {
++ public void run()
++ {
++ try
++ {
++ startSignal.await();
++ con.wait.set(mode != Mode.WRITE_FIRST);
++ writeAction.execute(parentNode);
++ }
++ catch (Exception e)
++ {
++ e.printStackTrace();
++ ex.set(e);
++ }
++ finally
++ {
++ if (mode == Mode.WRITE_FIRST) goSignal.countDown();
++ doneSignal.countDown();
++ }
++ }
++ };
++ writer.start();
++ Thread reader = new Thread()
++ {
++ public void run()
++ {
++ try
++ {
++ startSignal.await();
++ con.wait.set(mode != Mode.READ_FIRST);
++ readAction.execute(parentNode);
++ }
++ catch (Exception e)
++ {
++ e.printStackTrace();
++ ex.set(e);
++ }
++ finally
++ {
++ if (mode == Mode.READ_FIRST) goSignal.countDown();
++ doneSignal.countDown();
++ }
++ }
++ };
++ reader.start();
++ startSignal.countDown();
++ doneSignal.await();
++ assertNull(ex.get());
++ }
++
++ private abstract class Action
++ {
++
++ protected final CacheableWorkspaceDataManager cwdm;
++ public Action(CacheableWorkspaceDataManager cwdm)
++ {
++ this.cwdm = cwdm;
++ }
++ protected abstract void execute(NodeData parentNode) throws Exception;
++ }
++ private static enum Mode
++ {
++ READ_FIRST, WRITE_FIRST;
++ }
++ private static class MyWorkspaceStorageConnection implements WorkspaceStorageConnection
++ {
++ public ThreadLocal<Boolean> wait = new ThreadLocal<Boolean>();
++ private NodeData parentNode;
++ private CountDownLatch goSignal;
++
++ public CountDownLatch initCountDownLatch()
++ {
++ return this.goSignal = new CountDownLatch(1);
++ }
++
++ public void setParentNode(NodeData parentNode)
++ {
++ this.parentNode = parentNode;
++ }
++
++ public void add(NodeData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++
++ public void add(PropertyData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++
++ public void close() throws IllegalStateException, RepositoryException
++ {
++ }
++
++ public void commit() throws IllegalStateException, RepositoryException
++ {
++ if (wait.get() != null && wait.get())
++ {
++ try
++ {
++ goSignal.await();
++ }
++ catch (InterruptedException e)
++ {
++ Thread.currentThread().interrupt();
++ }
++ }
++ }
++
++ public void delete(NodeData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++
++ public void delete(PropertyData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++
++ public int getChildNodesCount(NodeData parent) throws RepositoryException
++ {
++ return -1;
++ }
++
++ public List<NodeData> getChildNodesData(NodeData parent) throws RepositoryException, IllegalStateException
++ {
++ if (wait.get() != null && wait.get())
++ {
++ try
++ {
++ goSignal.await();
++ }
++ catch (InterruptedException e)
++ {
++ Thread.currentThread().interrupt();
++ }
++ }
++ List<NodeData> children = new ArrayList<NodeData>();
++ children.add(new PersistedNodeData("id-node2" + parentNode.getIdentifier(), QPath.makeChildPath(parent.getQPath(), new InternalQName(null, "node2")), parent.getIdentifier(), 1, 0,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null));
++ return children;
++ }
++
++ public List<PropertyData> getChildPropertiesData(NodeData parent) throws RepositoryException,
++ IllegalStateException
++ {
++ if (wait.get() != null && wait.get())
++ {
++ try
++ {
++ goSignal.await();
++ }
++ catch (InterruptedException e)
++ {
++ Thread.currentThread().interrupt();
++ }
++ }
++ List<PropertyData> children = new ArrayList<PropertyData>();
++ try
++ {
++ children.add(new PersistedPropertyData("id-property2" + parentNode.getIdentifier(), QPath.makeChildPath(
++ parentNode.getQPath(), new InternalQName(null, "property2")), parentNode.getIdentifier(), 0,
++ PropertyType.STRING, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, "some data".getBytes("UTF-8")))));
++ }
++ catch (UnsupportedEncodingException e)
++ {
++ e.printStackTrace();
++ }
++ return children;
++ }
++
++ /**
++ * {@inheritDoc}
++ */
++ public ItemData getItemData(NodeData parentData, QPathEntry name) throws RepositoryException,
++ IllegalStateException
++ {
++ return getItemData(parentData, name, ItemType.UNKNOWN);
++ }
++
++ public ItemData getItemData(NodeData parentData, QPathEntry name, ItemType itemType) throws RepositoryException,
++ IllegalStateException
++ {
++ if (wait.get() != null && wait.get())
++ {
++ try
++ {
++ goSignal.await();
++ }
++ catch (InterruptedException e)
++ {
++ Thread.currentThread().interrupt();
++ }
++ }
++ if (itemType == ItemType.NODE)
++ {
++ return new PersistedNodeData("my-node" + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), name), Constants.ROOT_UUID, 1, 1,
++ Constants.NT_UNSTRUCTURED, new InternalQName[0], null);
++ }
++ try
++ {
++ return new PersistedPropertyData("property-by-path"
++ + parentNode.getIdentifier(), QPath.makeChildPath(parentNode.getQPath(), name), parentNode
++ .getIdentifier(), 1, PropertyType.STRING, false, Arrays
++ .asList((ValueData)new ByteArrayPersistedValueData(0, "some new data".getBytes("UTF-8"))));
++ }
++ catch (UnsupportedEncodingException e)
++ {
++ e.printStackTrace();
++ }
++ return null;
++ }
++
++ public ItemData getItemData(String identifier) throws RepositoryException, IllegalStateException
++ {
++ if (wait.get() != null && wait.get())
++ {
++ try
++ {
++ goSignal.await();
++ }
++ catch (InterruptedException e)
++ {
++ Thread.currentThread().interrupt();
++ }
++ }
++ return parentNode;
++ }
++
++ public List<PropertyData> getReferencesData(String nodeIdentifier) throws RepositoryException,
++ IllegalStateException, UnsupportedOperationException
++ {
++ if (wait.get() != null && wait.get())
++ {
++ try
++ {
++ goSignal.await();
++ }
++ catch (InterruptedException e)
++ {
++ Thread.currentThread().interrupt();
++ }
++ }
++ List<PropertyData> children = new ArrayList<PropertyData>();
++ try
++ {
++ children.add(new PersistedPropertyData("id-reference2" + parentNode.getIdentifier(), QPath.makeChildPath(
++ parentNode.getQPath(), new InternalQName(null, "reference2")), parentNode.getIdentifier(), 0,
++ PropertyType.REFERENCE, false, Arrays.asList((ValueData)new ByteArrayPersistedValueData(0, parentNode.getIdentifier().getBytes("UTF-8")))));
++ }
++ catch (UnsupportedEncodingException e)
++ {
++ e.printStackTrace();
++ }
++ return children;
++ }
++
++ public boolean isOpened()
++ {
++ return true;
++ }
++
++ public List<PropertyData> listChildPropertiesData(NodeData parent) throws RepositoryException,
++ IllegalStateException
++ {
++ return null;
++ }
++
++ public void rename(NodeData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++
++ public void rollback() throws IllegalStateException, RepositoryException
++ {
++ }
++
++ public void update(NodeData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++
++ public void update(PropertyData data) throws RepositoryException, UnsupportedOperationException,
++ InvalidItemStateException, IllegalStateException
++ {
++ }
++ };
++
++ private static class MyWorkspaceDataContainer extends WorkspaceDataContainerBase
++ {
++
++ private WorkspaceStorageConnection con;
++
++ public MyWorkspaceDataContainer(WorkspaceStorageConnection con)
++ {
++ this.con = con;
++ }
++
++ public boolean isCheckSNSNewConnection()
++ {
++ return false;
++ }
++
++ public boolean isSame(WorkspaceDataContainer another)
++ {
++ return false;
++ }
++
++ public WorkspaceStorageConnection openConnection() throws RepositoryException
++ {
++ return con;
++ }
++
++ public WorkspaceStorageConnection openConnection(boolean readOnly) throws RepositoryException
++ {
++ return con;
++ }
++
++ public WorkspaceStorageConnection reuseConnection(WorkspaceStorageConnection original) throws RepositoryException
++ {
++ return con;
++ }
++
++ public String getInfo()
++ {
++ return "MyWorkspaceDataContainer";
++ }
++
++ public String getName()
++ {
++ return "MyWorkspaceDataContainer";
++ }
++
++ public String getStorageVersion()
++ {
++ return "0";
++ }
++ };
++}
+\ No newline at end of file
+Index: exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml
+===================================================================
+--- exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml (revision 0)
++++ exo.jcr.component.core/src/test/resources/conf/standalone/cluster/test-jbosscache-data-no-mux.xml (revision 0)
+@@ -0,0 +1,24 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<jbosscache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:jboss:jbosscache-core:config:3.1">
++
++ <locking useLockStriping="false" concurrencyLevel="500" lockParentForChildInsertRemove="false"
++ lockAcquisitionTimeout="20000" />
++ <transaction syncRollbackPhase="true" syncCommitPhase="true" />
++
++ <clustering mode="replication" clusterName="${jbosscache-cluster-name}">
++ <stateRetrieval timeout="20000" fetchInMemoryState="false" />
++ <sync replTimeout="20000"/>
++ <jgroupsConfig configFile="udp.xml">
++ </jgroupsConfig>
++ </clustering>
++
++ <!-- Eviction configuration -->
++ <eviction wakeUpInterval="5000">
++ <default algorithmClass="org.jboss.cache.eviction.ExpirationAlgorithm"
++ actionPolicyClass="org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.ParentNodeEvictionActionPolicy"
++ eventQueueSize="1000000">
++ <property name="maxNodes" value="1000000" />
++ <property name="warnNoExpirationKey" value="false" />
++ </default>
++ </eviction>
++</jbosscache>
+\ No newline at end of file
Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java
===================================================================
---- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java (revision 4235)
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java (revision 4237)
+++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/BufferedJBossCache.java (working copy)
-@@ -471,6 +471,31 @@
+@@ -40,6 +40,7 @@
+ import java.util.Map;
+ import java.util.Set;
+
++import javax.transaction.Status;
+ import javax.transaction.TransactionManager;
+
+ /**
+@@ -64,6 +65,8 @@
+ private final boolean useExpiration;
+
+ private final long expirationTimeOut;
++
++ private final TransactionManager tm;
+
+ protected static final Log LOG =
+ ExoLogger.getLogger("org.exoplatform.services.jcr.impl.dataflow.persistent.jbosscache.BufferedJBossCache");
+@@ -71,6 +74,7 @@
+ public BufferedJBossCache(Cache<Serializable, Object> parentCache, boolean useExpiration, long expirationTimeOut)
+ {
+ super();
++ this.tm = ((CacheSPI<Serializable, Object>)parentCache).getTransactionManager();
+ this.parentCache = parentCache;
+ this.useExpiration = useExpiration;
+ this.expirationTimeOut = expirationTimeOut;
+@@ -109,7 +113,53 @@
+ //log.info("After=" + changesContainer.toString());
+ for (ChangesContainer cacheChange : containers)
+ {
+- cacheChange.apply();
++ boolean isTxCreated = false;
++ try
++ {
++ if (cacheChange.isTxRequired() && tm != null && tm.getStatus() == Status.STATUS_NO_TRANSACTION)
++ {
++ // No tx exists so we create a new tx
++ if (LOG.isTraceEnabled()) LOG.trace("No Tx is active we then create a new tx");
++ tm.begin();
++ isTxCreated = true;
++ }
++ }
++ catch (Exception e)
++ {
++ LOG.warn("Could not create a new tx", e);
++ }
++ try
++ {
++ cacheChange.apply();
++ }
++ catch (RuntimeException e)
++ {
++ if (isTxCreated)
++ {
++ try
++ {
++ if (LOG.isTraceEnabled()) LOG.trace("An error occurs the tx will be rollbacked");
++ tm.rollback();
++ }
++ catch (Exception e1)
++ {
++ LOG.warn("Could not rollback the tx", e1);
++ }
++ }
++ throw e;
++ }
++ if (isTxCreated)
++ {
++ try
++ {
++ if (LOG.isTraceEnabled()) LOG.trace("The tx will be committed");
++ tm.commit();
++ }
++ catch (Exception e)
++ {
++ LOG.warn("Could not commit the tx", e);
++ }
++ }
+ }
+ }
+ finally
+@@ -118,6 +168,7 @@
+ changesContainer = null;
+ }
+ }
++
+
+ /**
+ * Tries to get buffer and if it is null throws an exception otherwise returns buffer.
+@@ -471,6 +522,31 @@
return parentCache.get(fqn, key);
}
@@ -34,10 +806,22 @@
public Object putInBuffer(Fqn fqn, Serializable key, Object value)
{
CompressedChangesBuffer changesContainer = getChangesBufferSafe();
-@@ -789,6 +814,42 @@
+@@ -758,6 +834,11 @@
+ }
+
+ public abstract void apply();
++
++ public boolean isTxRequired()
++ {
++ return false;
++ }
}
/**
+@@ -789,6 +870,48 @@
+ }
+
+ /**
+ * PutIfAbsent container.
+ */
+ public static class PutIfAbsentKeyValueContainer extends ChangesContainer
@@ -71,15 +855,47 @@
+ setCacheLocalMode();
+ cache.put(fqn, key, value);
+ }
++
++ @Override
++ public boolean isTxRequired()
++ {
++ return true;
++ }
+ }
+
+ /**
* Put container.
*/
public static class PutKeyValueContainer extends ChangesContainer
+@@ -871,6 +994,12 @@
+ + existingObject.getClass().getName());
+ }
+ }
++
++ @Override
++ public boolean isTxRequired()
++ {
++ return true;
++ }
+ }
+
+ /**
+@@ -913,6 +1042,12 @@
+ cache.put(fqn, key, newSet);
+ }
+ }
++
++ @Override
++ public boolean isTxRequired()
++ {
++ return false;
++ }
+ }
+
+ /**
Index: exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
---- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java (revision 4235)
+--- exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java (revision 4237)
+++ exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java (working copy)
@@ -60,6 +60,7 @@
More information about the exo-jcr-commits
mailing list