Author: sergiykarpenko
Date: 2010-11-05 11:33:42 -0400 (Fri, 05 Nov 2010)
New Revision: 3402
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullItemData.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullNodeData.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullPropertyData.java
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
Log:
EXOJCR-1006: allow to keep missing values into the JCR cache based on ISPN
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullItemData.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullItemData.java
(rev 0)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullItemData.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.datamodel;
+
+import org.exoplatform.services.jcr.dataflow.ItemDataVisitor;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: NullItemData.java 111 2008-11-11 11:11:11Z serg $
+ */
+public abstract class NullItemData implements ItemData
+{
+
+ public static final String NULL_ID = "_null_id";
+
+ private final String id;
+
+ private final String parentId;
+
+ private final QPath path;
+
+ public NullItemData(NodeData parentData, QPathEntry name)
+ {
+ this.parentId = parentData.getIdentifier();
+ this.path = QPath.makeChildPath(parentData.getQPath(), name);
+ this.id = NULL_ID;
+ }
+
+ /**
+ * This constructor must never be used for null nodes placed in cache. Only for
returned values.
+ *
+ * @param parentId
+ * @param name
+ */
+ public NullItemData(String parentId, QPathEntry name)
+ {
+ this.parentId = parentId;
+ this.path = null;
+ this.id = NULL_ID;
+ }
+
+ public NullItemData(String id)
+ {
+ this.parentId = null;
+ this.path = null;
+ this.id = id;
+ }
+
+ public void accept(ItemDataVisitor visitor) throws RepositoryException
+ {
+ }
+
+ public String getIdentifier()
+ {
+ return id;
+ }
+
+ public String getParentIdentifier()
+ {
+ return parentId;
+ }
+
+ public int getPersistedVersion()
+ {
+ return 0;
+ }
+
+ public QPath getQPath()
+ {
+ return path;
+ }
+
+}
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullNodeData.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullNodeData.java
(rev 0)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullNodeData.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 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.datamodel;
+
+import org.exoplatform.services.jcr.access.AccessControlList;
+
+/**
+ * This class is used to represent <code>null</code> value, it is designed to
be used
+ * into the cache to represent missing value.
+ *
+ * @author <a href="anatoliy.bazko(a)exoplatform.org">Anatoliy
Bazko</a>
+ * @version $Id: NullNodeData.java 111 2010-11-11 11:11:11Z tolusha $
+ */
+public class NullNodeData extends NullItemData implements NodeData
+{
+ public NullNodeData(NodeData parentData, QPathEntry name)
+ {
+ super(parentData, name);
+ }
+
+ /**
+ * This constructor must never be used for null nodes placed in cache. Only for
returned values.
+ *
+ * @param parentId
+ * @param name
+ */
+ public NullNodeData(String parentId, QPathEntry name)
+ {
+ super(parentId, name);
+ }
+
+ public NullNodeData(String id)
+ {
+ super(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isNode()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public AccessControlList getACL()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InternalQName[] getMixinTypeNames()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getOrderNumber()
+ {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public InternalQName getPrimaryTypeName()
+ {
+ return null;
+ }
+
+}
Added:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullPropertyData.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullPropertyData.java
(rev 0)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/datamodel/NullPropertyData.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2003-2010 eXo Platform SAS.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not,
see<http://www.gnu.org/licenses/>.
+ */
+package org.exoplatform.services.jcr.datamodel;
+
+import java.util.List;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: NullPropertyData.java 111 2008-11-11 11:11:11Z serg $
+ */
+public class NullPropertyData extends NullItemData implements PropertyData
+{
+
+ public NullPropertyData(NodeData parentData, QPathEntry name)
+ {
+ super(parentData, name);
+ }
+
+ public NullPropertyData(String id)
+ {
+ super(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getType()
+ {
+ return -1;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<ValueData> getValues()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isMultiValued()
+ {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isNode()
+ {
+ return false;
+ }
+
+}
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2010-11-05
10:46:02 UTC (rev 3401)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/CacheableWorkspaceDataManager.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -23,6 +23,9 @@
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.NullItemData;
+import org.exoplatform.services.jcr.datamodel.NullNodeData;
+import org.exoplatform.services.jcr.datamodel.NullPropertyData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.datamodel.ValueData;
@@ -410,18 +413,20 @@
{
data = getPersistedItemData(parentData, name, itemType);
}
- else if (!data.isNode())
- {
- fixPropertyValues((PropertyData)data);
- }
}
finally
{
request.done();
}
}
- else if (!data.isNode())
+
+ if (data instanceof NullItemData)
{
+ return null;
+ }
+
+ if (data != null && !data.isNode())
+ {
fixPropertyValues((PropertyData)data);
}
@@ -452,18 +457,20 @@
{
data = getPersistedItemData(identifier);
}
- else if (!data.isNode())
- {
- fixPropertyValues((PropertyData)data);
- }
}
finally
{
request.done();
}
}
- else if (!data.isNode())
+
+ if (data instanceof NullItemData)
{
+ return null;
+ }
+
+ if (data != null && !data.isNode())
+ {
fixPropertyValues((PropertyData)data);
}
@@ -676,11 +683,26 @@
throws RepositoryException
{
ItemData data = super.getItemData(parentData, name, itemType);
- if (data != null && cache.isEnabled())
+ if (cache.isEnabled())
{
- cache.put(data);
+ if (data == null)
+ {
+ if (itemType == ItemType.NODE || itemType == ItemType.UNKNOWN)
+ {
+ cache.put(new NullNodeData(parentData, name));
+ }
+ else
+ {
+ cache.put(new NullPropertyData(parentData, name));
+ }
+ }
+ else
+ {
+ cache.put(data);
+ }
}
return data;
+
}
/**
@@ -693,9 +715,17 @@
protected ItemData getPersistedItemData(String identifier) throws RepositoryException
{
ItemData data = super.getItemData(identifier);
- if (data != null && cache.isEnabled())
+ if (cache.isEnabled())
{
- cache.put(data);
+ if (data != null)
+ {
+ cache.put(data);
+ }
+ else if (identifier != null)
+ {
+ // no matter does property or node expected - store NullNodeData
+ cache.put(new NullNodeData(identifier));
+ }
}
return data;
}
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java 2010-11-05
10:46:02 UTC (rev 3401)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/LinkedWorkspaceStorageCacheImpl.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -27,6 +27,7 @@
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.NullItemData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
@@ -42,10 +43,10 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Timer;
import java.util.TimerTask;
import java.util.WeakHashMap;
+import java.util.Map.Entry;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.ReentrantLock;
@@ -938,6 +939,12 @@
if (enabled && item != null)
{
+ if (item instanceof NullItemData)
+ {
+ // skip null values
+ return;
+ }
+
writeLock.lock();
try
{
@@ -1071,7 +1078,7 @@
{
if (enabled && parentData != null && childItems != null)
{ // TODO don't check parentData !=
- // null && childItems != null
+ // null && childItems != null
String logInfo = null;
if (LOG.isDebugEnabled())
@@ -1133,7 +1140,7 @@
{
if (enabled && parentData != null && childItems != null)
{ // TODO don't check parentData !=
- // null && childItems != null
+ // null && childItems != null
String logInfo = null;
if (LOG.isDebugEnabled())
@@ -1184,7 +1191,7 @@
{
if (enabled && parentData != null && childItems != null)
{ // TODO don't check parentData !=
- // null && childItems != null
+ // null && childItems != null
String logInfo = null;
if (LOG.isDebugEnabled())
@@ -1662,7 +1669,8 @@
{
writeLock.unlock();
}
- LOG.info(name + " : set liveTime=" + liveTime + "ms. New value will
be applied to items cached from this moment.");
+ LOG
+ .info(name + " : set liveTime=" + liveTime + "ms. New value will
be applied to items cached from this moment.");
}
/**
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java 2010-11-05
10:46:02 UTC (rev 3401)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/VersionableWorkspaceDataManager.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -28,6 +28,7 @@
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.NullItemData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
@@ -157,18 +158,22 @@
{
// from cache at first
ItemData cdata = persistentManager.getCachedItemData(identifier);
- if (cdata != null)
+ if (cdata != null && !(cdata instanceof NullItemData))
+ {
return super.getItemData(identifier);
+ }
if (!this.equals(versionDataManager) &&
!identifier.equals(Constants.ROOT_UUID))
{
// search in System cache for /jcr:system nodes only
cdata = versionDataManager.persistentManager.getCachedItemData(identifier);
- if (cdata != null)
+ if (cdata != null && !(cdata instanceof NullItemData))
+ {
if (isSystemDescendant(cdata.getQPath()))
return versionDataManager.getItemData(identifier);
else
return null;
+ }
}
// then from persistence
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java 2010-11-05
10:46:02 UTC (rev 3401)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/BufferedISPNCache.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -39,6 +39,8 @@
import java.util.Set;
import java.util.concurrent.TimeUnit;
+import javax.transaction.TransactionManager;
+
/**
* Decorator over the Infinispan Cache that stores changes in buffer, then sorts and
applies it.
*
@@ -744,7 +746,7 @@
return withReturnValue ? parentCache.get(key) : null;
}
-
+
/**
* {@inheritDoc}
*/
@@ -919,6 +921,11 @@
return changesContainer;
}
+ public TransactionManager getTransactionManager()
+ {
+ return parentCache.getTransactionManager();
+ }
+
/**
*
* @param key
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2010-11-05
10:46:02 UTC (rev 3401)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/infinispan/ISPNCacheWorkspaceStorageCache.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -31,6 +31,9 @@
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.NullItemData;
+import org.exoplatform.services.jcr.datamodel.NullNodeData;
+import org.exoplatform.services.jcr.datamodel.NullPropertyData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
@@ -53,6 +56,8 @@
import java.util.Set;
import javax.jcr.RepositoryException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
/**
* Created by The eXo Platform SAS.<p/>
@@ -87,7 +92,6 @@
*/
class NodesOrderComparator<N extends NodeData> implements
Comparator<NodeData>
{
-
/**
* {@inheritDoc}
*/
@@ -229,6 +233,13 @@
*/
public void put(ItemData item)
{
+ // There is different commit processing for NullNodeData and ordinary ItemData.
+ if (item instanceof NullItemData)
+ {
+ putNullItem((NullItemData)item);
+ return;
+ }
+
boolean inTransaction = cache.isTransactionActive();
try
{
@@ -434,20 +445,45 @@
*/
public ItemData get(String parentIdentifier, QPathEntry name, ItemType itemType)
{
- String id = null;
- if (itemType == ItemType.NODE || itemType == ItemType.UNKNOWN)
+ String itemId = null;
+
+ if (itemType == ItemType.UNKNOWN)
{
- // try as node first
- id = (String)cache.get(new CacheQPath(parentIdentifier, name, ItemType.NODE));
+ // Try as node first.
+ itemId = (String)cache.get(new CacheQPath(parentIdentifier, name,
ItemType.NODE));
+
+ if (itemId == null || itemId.equals(NullItemData.NULL_ID))
+ {
+ // node with such a name is not found or marked as not-exist, so check the
properties
+ String propId = (String)cache.get(new CacheQPath(parentIdentifier, name,
ItemType.PROPERTY));
+ if (propId != null)
+ {
+ itemId = propId;
+ }
+ }
}
+ else if (itemType == ItemType.NODE)
+ {
+ itemId = (String)cache.get(new CacheQPath(parentIdentifier, name,
ItemType.NODE));;
+ }
+ else
+ {
+ itemId = (String)cache.get(new CacheQPath(parentIdentifier, name,
ItemType.PROPERTY));;
+ }
- if (itemType == ItemType.PROPERTY || itemType == ItemType.UNKNOWN && id ==
null)
+ if (itemId != null)
{
- // try as property
- id = (String)cache.get(new CacheQPath(parentIdentifier, name,
ItemType.PROPERTY));
+ if (itemId.equals(NullItemData.NULL_ID))
+ {
+ // this NullNodeData object will not be placed at cache, so we can use unsafe
constructor
+ return new NullNodeData(parentIdentifier, name);
+ }
+ else
+ {
+ return get(itemId);
+ }
}
-
- return get(id);
+ return null;
}
/**
@@ -638,10 +674,50 @@
}
}
- return (ItemData)cache.putInBuffer(new CacheId(node.getIdentifier()), node);
+ // NullNodeData must never be returned inside internal cache operations.
+ ItemData itemData = (ItemData)cache.putInBuffer(new CacheId(node.getIdentifier()),
node);
+ return (itemData instanceof NullItemData) ? null : itemData;
}
/**
+ * Internal put NullNode.
+ *
+ * @param node, NodeData, new data to put in the cache
+ */
+ protected void putNullItem(NullItemData node)
+ {
+ boolean inTransaction = cache.isTransactionActive();
+ try
+ {
+ if (!inTransaction)
+ {
+ cache.beginTransaction();
+ }
+ cache.setLocal(true);
+
+ if (node.getQPath() == null)
+ {
+ //put in $ITEMS
+ cache.put(new CacheId(node.getIdentifier()), node);
+ }
+ else
+ {
+
+ cache.put(new CacheQPath(node.getParentIdentifier(), node.getQPath(),
(node.isNode() ? ItemType.NODE
+ : ItemType.PROPERTY)), node.getIdentifier());
+ }
+ }
+ finally
+ {
+ cache.setLocal(false);
+ if (!inTransaction)
+ {
+ dedicatedTxCommit();
+ }
+ }
+ }
+
+ /**
* Internal put Property.
*
* @param node, PropertyData, new data to put in the cache
@@ -657,7 +733,10 @@
}
cache.put(new CacheQPath(prop.getParentIdentifier(), prop.getQPath(),
ItemType.PROPERTY), prop.getIdentifier());
- return (PropertyData)cache.put(new CacheId(prop.getIdentifier()), prop, true);
+
+ // NullItemData must never be returned inside internal cache operations.
+ PropertyData propData = (PropertyData)cache.put(new CacheId(prop.getIdentifier()),
prop, true);
+ return (propData instanceof NullPropertyData) ? null : propData;
}
protected void removeItem(ItemData item)
@@ -689,19 +768,22 @@
protected void updateMixin(NodeData node)
{
NodeData prevData = (NodeData)cache.put(new CacheId(node.getIdentifier()), node,
true);
-
- if (prevData != null)
+ // prevent update NullNodeData
+ if (!(prevData instanceof NullNodeData))
{
- // do update ACL if needed
- if (prevData.getACL() == null || !prevData.getACL().equals(node.getACL()))
+ if (prevData != null)
{
- updateChildsACL(node.getIdentifier(), node.getACL());
+ // do update ACL if needed
+ if (prevData.getACL() == null || !prevData.getACL().equals(node.getACL()))
+ {
+ updateChildsACL(node.getIdentifier(), node.getACL());
+ }
}
+ else if (LOG.isDebugEnabled())
+ {
+ LOG.debug("Previous NodeData not found for mixin update " +
node.getQPath().getAsString());
+ }
}
- else if (LOG.isDebugEnabled())
- {
- LOG.debug("Previous NodeData not found for mixin update " +
node.getQPath().getAsString());
- }
}
/**
@@ -714,6 +796,7 @@
*/
protected void updateInBuffer(final NodeData node, final NodeData prevNode)
{
+ // I expect that NullNodeData will never update existing NodeData.
CacheQPath prevKey = new CacheQPath(node.getParentIdentifier(),
prevNode.getQPath(), ItemType.NODE);
if (node.getIdentifier().equals(cache.getFromBuffer(prevKey)))
{
@@ -755,7 +838,8 @@
{
// check is this descendant of prevRootPath
QPath nodeQPath = data.getQPath();
- if (nodeQPath.isDescendantOf(prevRootPath))
+ // NullNodeData's qPath==null;
+ if (nodeQPath != null && nodeQPath.isDescendantOf(prevRootPath))
{
//make relative path
@@ -878,4 +962,45 @@
NOT_MODIFY, MODIFY, FORCE_MODIFY
}
+ /**
+ * Allows to commit the cache changes in a dedicated XA Tx in order to avoid
potential
+ * deadlocks
+ */
+ private void dedicatedTxCommit()
+ {
+ // Ensure that the commit is done in a dedicated tx to avoid deadlock due
+ // to global XA Tx
+ TransactionManager tm = cache.getTransactionManager();
+ Transaction tx = null;
+ try
+ {
+ if (tm != null)
+ {
+ try
+ {
+ tx = tm.suspend();
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot suspend the current transaction", e);
+ }
+ }
+ cache.commitTransaction();
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ try
+ {
+ tm.resume(tx);
+ }
+ catch (Exception e)
+ {
+ LOG.warn("Cannot resume the current transaction", e);
+ }
+ }
+ }
+ }
+
}
Modified:
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java
===================================================================
---
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2010-11-05
10:46:02 UTC (rev 3401)
+++
jcr/branches/1.14-ISPN/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/dataflow/persistent/jbosscache/JBossCacheWorkspaceStorageCache.java 2010-11-05
15:33:42 UTC (rev 3402)
@@ -30,6 +30,7 @@
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.NullItemData;
import org.exoplatform.services.jcr.datamodel.PropertyData;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
@@ -386,6 +387,13 @@
*/
public void put(ItemData item)
{
+ // TODO its temporary
+ if (item instanceof NullItemData)
+ {
+ // skip null values
+ return;
+ }
+
boolean inTransaction = cache.isTransactionActive();
try
{
@@ -840,16 +848,15 @@
if (node.getParentIdentifier() != null)
{
// add in CHILD_NODES
- cache.put(
- makeChildFqn(childNodes, node.getParentIdentifier(),
node.getQPath().getEntries()[node.getQPath()
- .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
+ cache.put(makeChildFqn(childNodes, node.getParentIdentifier(),
node.getQPath().getEntries()[node.getQPath()
+ .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
// if MODIFY and List present OR FORCE_MODIFY, then write
- if ((modifyListsOfChild == ModifyChildOption.MODIFY &&
cache.getNode(makeChildListFqn(childNodesList,
- node.getParentIdentifier())) != null)
+ if ((modifyListsOfChild == ModifyChildOption.MODIFY &&
cache.getNode(makeChildListFqn(childNodesList, node
+ .getParentIdentifier())) != null)
|| modifyListsOfChild == ModifyChildOption.FORCE_MODIFY)
{
- cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()),
ITEM_LIST,
- node.getIdentifier());
+ cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()),
ITEM_LIST, node
+ .getIdentifier());
}
}
@@ -863,16 +870,15 @@
if (node.getParentIdentifier() != null)
{
// add in CHILD_NODES
- cache.put(
- makeChildFqn(childNodes, node.getParentIdentifier(),
node.getQPath().getEntries()[node.getQPath()
- .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
+ cache.put(makeChildFqn(childNodes, node.getParentIdentifier(),
node.getQPath().getEntries()[node.getQPath()
+ .getEntries().length - 1]), ITEM_ID, node.getIdentifier());
// if MODIFY and List present OR FORCE_MODIFY, then write
- if ((modifyListsOfChild == ModifyChildOption.MODIFY &&
cache.getNode(makeChildListFqn(childNodesList,
- node.getParentIdentifier())) != null)
+ if ((modifyListsOfChild == ModifyChildOption.MODIFY &&
cache.getNode(makeChildListFqn(childNodesList, node
+ .getParentIdentifier())) != null)
|| modifyListsOfChild == ModifyChildOption.FORCE_MODIFY)
{
- cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()),
ITEM_LIST,
- node.getIdentifier());
+ cache.addToList(makeChildListFqn(childNodesList, node.getParentIdentifier()),
ITEM_LIST, node
+ .getIdentifier());
}
}
// add in ITEMS
@@ -888,12 +894,11 @@
protected PropertyData putProperty(PropertyData prop, ModifyChildOption
modifyListsOfChild)
{
// add in CHILD_PROPS
- cache.put(
- makeChildFqn(childProps, prop.getParentIdentifier(),
- prop.getQPath().getEntries()[prop.getQPath().getEntries().length - 1]),
ITEM_ID, prop.getIdentifier());
+ cache.put(makeChildFqn(childProps, prop.getParentIdentifier(),
prop.getQPath().getEntries()[prop.getQPath()
+ .getEntries().length - 1]), ITEM_ID, prop.getIdentifier());
// if MODIFY and List present OR FORCE_MODIFY, then write
- if ((modifyListsOfChild == ModifyChildOption.MODIFY &&
cache.getNode(makeChildListFqn(childPropsList,
- prop.getParentIdentifier())) != null)
+ if ((modifyListsOfChild == ModifyChildOption.MODIFY &&
cache.getNode(makeChildListFqn(childPropsList, prop
+ .getParentIdentifier())) != null)
|| modifyListsOfChild == ModifyChildOption.FORCE_MODIFY)
{
cache.addToList(makeChildListFqn(childPropsList, prop.getParentIdentifier()),
ITEM_LIST, prop.getIdentifier());
@@ -915,8 +920,8 @@
.getQPath().getEntries().length - 1]));
// remove from CHILD_NODES_LIST of parent
- cache.removeFromList(makeChildListFqn(childNodesList,
item.getParentIdentifier()), ITEM_LIST,
- item.getIdentifier());
+ cache.removeFromList(makeChildListFqn(childNodesList,
item.getParentIdentifier()), ITEM_LIST, item
+ .getIdentifier());
// remove from CHILD_NODES as parent
cache.removeNode(makeChildListFqn(childNodes, item.getIdentifier()));
@@ -938,8 +943,8 @@
.getQPath().getEntries().length - 1]));
// remove from CHILD_PROPS_LIST
- cache.removeFromList(makeChildListFqn(childPropsList,
item.getParentIdentifier()), ITEM_LIST,
- item.getIdentifier());
+ cache.removeFromList(makeChildListFqn(childPropsList,
item.getParentIdentifier()), ITEM_LIST, item
+ .getIdentifier());
}
// remove from ITEMS
cache.removeNode(makeItemFqn(item.getIdentifier()));
@@ -1077,9 +1082,9 @@
NodeData prevNode = (NodeData)data;
TransientNodeData newNode =
- new TransientNodeData(newPath, prevNode.getIdentifier(),
prevNode.getPersistedVersion(),
- prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(),
prevNode.getOrderNumber(),
- prevNode.getParentIdentifier(), inheritACL ? acl :
prevNode.getACL()); // TODO check ACL
+ new TransientNodeData(newPath, prevNode.getIdentifier(),
prevNode.getPersistedVersion(), prevNode
+ .getPrimaryTypeName(), prevNode.getMixinTypeNames(),
prevNode.getOrderNumber(), prevNode
+ .getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); //
TODO check ACL
// update this node
cache.put(makeItemFqn(newNode.getIdentifier()), ITEM_DATA, newNode);
}
@@ -1097,8 +1102,8 @@
}
TransientPropertyData newProp =
- new TransientPropertyData(newPath, prevProp.getIdentifier(),
prevProp.getPersistedVersion(),
- prevProp.getType(), prevProp.getParentIdentifier(),
prevProp.isMultiValued(), prevProp.getValues());
+ new TransientPropertyData(newPath, prevProp.getIdentifier(),
prevProp.getPersistedVersion(), prevProp
+ .getType(), prevProp.getParentIdentifier(),
prevProp.isMultiValued(), prevProp.getValues());
cache.put(makeItemFqn(newProp.getIdentifier()), ITEM_DATA, newProp);
}
}
@@ -1132,8 +1137,8 @@
QPath
.makeChildPath(rootPath,
prevProp.getQPath().getEntries()[prevProp.getQPath().getEntries().length - 1]);
TransientPropertyData newProp =
- new TransientPropertyData(newPath, prevProp.getIdentifier(),
prevProp.getPersistedVersion(),
- prevProp.getType(), prevProp.getParentIdentifier(),
prevProp.isMultiValued(), prevProp.getValues());
+ new TransientPropertyData(newPath, prevProp.getIdentifier(),
prevProp.getPersistedVersion(), prevProp
+ .getType(), prevProp.getParentIdentifier(), prevProp.isMultiValued(),
prevProp.getValues());
cache.put(makeItemFqn(newProp.getIdentifier()), ITEM_DATA, newProp);
}
@@ -1146,9 +1151,9 @@
QPath
.makeChildPath(rootPath,
prevNode.getQPath().getEntries()[prevNode.getQPath().getEntries().length - 1]);
TransientNodeData newNode =
- new TransientNodeData(newPath, prevNode.getIdentifier(),
prevNode.getPersistedVersion(),
- prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(),
prevNode.getOrderNumber(),
- prevNode.getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); //
TODO check ACL
+ new TransientNodeData(newPath, prevNode.getIdentifier(),
prevNode.getPersistedVersion(), prevNode
+ .getPrimaryTypeName(), prevNode.getMixinTypeNames(),
prevNode.getOrderNumber(), prevNode
+ .getParentIdentifier(), inheritACL ? acl : prevNode.getACL()); // TODO
check ACL
// update this node
cache.put(makeItemFqn(newNode.getIdentifier()), ITEM_DATA, newNode);
// update childs recursive
@@ -1178,8 +1183,8 @@
// recreate with new path for child Nodes only
TransientNodeData newNode =
new TransientNodeData(prevNode.getQPath(), prevNode.getIdentifier(),
prevNode.getPersistedVersion(),
- prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(),
prevNode.getOrderNumber(),
- prevNode.getParentIdentifier(), acl);
+ prevNode.getPrimaryTypeName(), prevNode.getMixinTypeNames(),
prevNode.getOrderNumber(), prevNode
+ .getParentIdentifier(), acl);
// update this node
cache.put(makeItemFqn(newNode.getIdentifier()), ITEM_DATA, newNode);
// update childs recursive