[jbosscache-commits] JBoss Cache SVN: r6749 - in core/trunk/src/main/java/org/jboss/cache: mvcc and 1 other directory.
jbosscache-commits at lists.jboss.org
jbosscache-commits at lists.jboss.org
Thu Sep 18 07:02:46 EDT 2008
Author: manik.surtani at jboss.com
Date: 2008-09-18 07:02:45 -0400 (Thu, 18 Sep 2008)
New Revision: 6749
Modified:
core/trunk/src/main/java/org/jboss/cache/AbstractNode.java
core/trunk/src/main/java/org/jboss/cache/AbstractNodeFactory.java
core/trunk/src/main/java/org/jboss/cache/DataContainer.java
core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
core/trunk/src/main/java/org/jboss/cache/InternalNode.java
core/trunk/src/main/java/org/jboss/cache/NodeFactory.java
core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeFactory.java
core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeHelper.java
core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java
core/trunk/src/main/java/org/jboss/cache/mvcc/NullMarkerNode.java
core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java
core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java
Log:
Optimised for performance, minimising additional node lookups on completion of an update
Modified: core/trunk/src/main/java/org/jboss/cache/AbstractNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/AbstractNode.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/AbstractNode.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -227,6 +227,11 @@
throw new UnsupportedOperationException("Not supported in " + getClass().getSimpleName());
}
+ public void addChild(InternalNode<K, V> child, boolean safe)
+ {
+ throw new UnsupportedOperationException("Not supported in " + getClass().getSimpleName());
+ }
+
public void setChildrenMap(ConcurrentMap<Object, InternalNode<K, V>> children)
{
throw new UnsupportedOperationException("Not supported in " + getClass().getSimpleName());
Modified: core/trunk/src/main/java/org/jboss/cache/AbstractNodeFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/AbstractNodeFactory.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/AbstractNodeFactory.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -105,7 +105,7 @@
throw new UnsupportedOperationException("Unsupported in this implementation (" + getClass().getSimpleName() + ")!");
}
- public ReadCommittedNode createWrappedNode(InternalNode<K, V> node)
+ public ReadCommittedNode createWrappedNode(InternalNode<K, V> node, InternalNode<K, V> parent)
{
throw new UnsupportedOperationException("Unsupported in this implementation (" + getClass().getSimpleName() + ")!");
}
Modified: core/trunk/src/main/java/org/jboss/cache/DataContainer.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -192,6 +192,15 @@
InternalNode peekInternalNode(Fqn f, boolean includeInvalidNodes);
/**
+ * Similar to {@link #peekInternalNode(Fqn, boolean)} except that the node AND it's *direct* parent are retrieved.
+ *
+ * @param fqn fqn to find
+ * @param includeInvalidNodes if true, invalid nodes are considered.
+ * @return an array of InternalNodes, containing 2 elements. Element [0] is the node being peeked, and element [1] is it's direct parent.
+ */
+ public InternalNode[] peekInternalNodeAndDirectParent(Fqn fqn, boolean includeInvalidNodes);
+
+ /**
* Sets a new root node
*
* @param nodeInvocationDelegate
Modified: core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -47,6 +47,7 @@
private BuddyFqnTransformer buddyFqnTransformer;
private Configuration config;
private boolean usingMvcc;
+ private static final InternalNode[] NULL_ARRAY = {null, null};
@Inject
public void injectDependencies(NodeFactory nodeFactory, LockManager lockManager, BuddyFqnTransformer transformer, Configuration configuration)
@@ -724,6 +725,36 @@
return n;
}
+ /**
+ * Similar to {@link #peekInternalNode(Fqn, boolean)} except that the node AND it's *direct* parent are retrieved.
+ *
+ * @param fqn fqn to find
+ * @param includeInvalidNodes if true, invalid nodes are considered.
+ * @return an array of InternalNodes, containing 2 elements. Element [0] is the node being peeked, and element [1] is it's direct parent.
+ */
+ public InternalNode[] peekInternalNodeAndDirectParent(Fqn fqn, boolean includeInvalidNodes)
+ {
+ if (fqn == null || fqn.size() == 0) return new InternalNode[]{rootInternal, null};
+ InternalNode n = rootInternal;
+ InternalNode directParent = null;
+ int fqnSize = fqn.size();
+ for (int i = 0; i < fqnSize; i++)
+ {
+ directParent = n;
+ Object obj = fqn.get(i);
+ n = directParent.getChild(obj);
+ if (n == null)
+ {
+ return NULL_ARRAY;
+ }
+ else if (!includeInvalidNodes && !n.isValid())
+ {
+ return NULL_ARRAY;
+ }
+ }
+ return new InternalNode[]{n, directParent};
+ }
+
public void setBuddyFqnTransformer(BuddyFqnTransformer buddyFqnTransformer)
{
this.buddyFqnTransformer = buddyFqnTransformer;
Modified: core/trunk/src/main/java/org/jboss/cache/InternalNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/InternalNode.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/InternalNode.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -117,6 +117,15 @@
void addChild(InternalNode<K, V> child);
+ /**
+ * Same as above, except that if safe is true, any Fqn ancestry checking is skipped. Don't set safe to true unless
+ * you really know what you are doing!
+ *
+ * @param child child to add
+ * @param safe safety flag
+ */
+ void addChild(InternalNode<K, V> child, boolean safe);
+
// *****************End new methods *****************
Modified: core/trunk/src/main/java/org/jboss/cache/NodeFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/NodeFactory.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/NodeFactory.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -15,7 +15,7 @@
*/
public interface NodeFactory<K, V>
{
- ReadCommittedNode createWrappedNode(InternalNode<K, V> node);
+ ReadCommittedNode createWrappedNode(InternalNode<K, V> node, InternalNode<K, V> parent);
WorkspaceNode<K, V> createWrappedNode(NodeSPI<K, V> dataNode, TransactionWorkspace workspace);
Modified: core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -18,6 +18,9 @@
import org.jboss.cache.factories.annotations.Stop;
import org.jboss.cache.interceptors.InterceptorChain;
import org.jboss.cache.invocation.InvocationContextContainer;
+import org.jboss.cache.jmx.annotations.MBean;
+import org.jboss.cache.jmx.annotations.ManagedAttribute;
+import org.jboss.cache.jmx.annotations.ManagedOperation;
import org.jboss.cache.lock.LockManager;
import org.jboss.cache.lock.LockUtil;
import org.jboss.cache.lock.TimeoutException;
@@ -31,9 +34,6 @@
import org.jboss.cache.transaction.TransactionTable;
import org.jboss.cache.util.ThreadGate;
import org.jboss.cache.util.reflect.ReflectionUtil;
-import org.jboss.cache.jmx.annotations.ManagedOperation;
-import org.jboss.cache.jmx.annotations.ManagedAttribute;
-import org.jboss.cache.jmx.annotations.MBean;
import org.jgroups.Address;
import org.jgroups.Channel;
import org.jgroups.ChannelException;
@@ -42,14 +42,15 @@
import org.jgroups.JChannel;
import org.jgroups.StateTransferException;
import org.jgroups.View;
+import org.jgroups.blocks.GroupRequest;
+import org.jgroups.blocks.RspFilter;
import org.jgroups.protocols.TP;
import org.jgroups.stack.ProtocolStack;
-import org.jgroups.blocks.GroupRequest;
-import org.jgroups.blocks.RspFilter;
import org.jgroups.util.Rsp;
import org.jgroups.util.RspList;
import javax.transaction.TransactionManager;
+import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -57,14 +58,13 @@
import java.util.List;
import java.util.Set;
import java.util.Vector;
-import java.text.NumberFormat;
/**
* Manager that handles all RPC calls between JBoss Cache instances
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani (manik at jboss.org)</a>
*/
- at MBean (objectName = "RPCManager")
+ at MBean(objectName = "RPCManager")
public class RPCManagerImpl implements RPCManager
{
private Channel channel;
@@ -72,7 +72,7 @@
private List<Address> members;
private long replicationCount;
private long replicationFailures;
- private boolean statisticsEnabled;
+ private boolean statisticsEnabled = false;
private final Object coordinatorLock = new Object();
/**
@@ -417,7 +417,8 @@
public List<Object> callRemoteMethods(Vector<Address> recipients, ReplicableCommand command, int mode, long timeout, RspFilter responseFilter, boolean useOutOfBandMessage) throws Exception
{
boolean success = true;
- try {
+ try
+ {
// short circuit if we don't have an RpcDispatcher!
if (rpcDispatcher == null) return null;
int modeToUse = mode;
@@ -469,10 +470,14 @@
}
}
return retval;
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
success = false;
throw e;
- } finally {
+ }
+ finally
+ {
computeStats(success);
}
}
@@ -538,7 +543,7 @@
}
catch (Exception transferFailed)
{
- if (log.isTraceEnabled()) log.trace("Error while fetching state",transferFailed);
+ if (log.isTraceEnabled()) log.trace("Error while fetching state", transferFailed);
successfulTransfer = false;
}
}
@@ -707,17 +712,18 @@
}
-
//jmx operations
- private void computeStats(boolean success) {
- if (this.isStatisticsEnabled() && rpcDispatcher != null)
+ private void computeStats(boolean success)
+ {
+ if (statisticsEnabled && rpcDispatcher != null)
{
if (success)
{
- replicationCount ++;
- } else
+ replicationCount++;
+ }
+ else
{
- replicationFailures ++;
+ replicationFailures++;
}
}
}
@@ -730,22 +736,26 @@
}
@ManagedAttribute(description = "number of successful replications")
- public long getReplicationCount() {
+ public long getReplicationCount()
+ {
return replicationCount;
}
- @ManagedAttribute (description = "number of failed replications")
- public long getReplicationFailures() {
+ @ManagedAttribute(description = "number of failed replications")
+ public long getReplicationFailures()
+ {
return replicationFailures;
}
- @ManagedAttribute (description = "whether or not jmx statistics are enabled")
- public boolean isStatisticsEnabled() {
+ @ManagedAttribute(description = "whether or not jmx statistics are enabled")
+ public boolean isStatisticsEnabled()
+ {
return statisticsEnabled;
}
@ManagedAttribute
- public void setStatisticsEnabled(boolean statisticsEnabled) {
+ public void setStatisticsEnabled(boolean statisticsEnabled)
+ {
this.statisticsEnabled = statisticsEnabled;
}
@@ -757,8 +767,8 @@
return "N/A";
}
double totalCount = replicationCount + replicationFailures;
- double ration = (double)replicationCount / totalCount * 100d;
- return NumberFormat.getInstance().format(ration) +"%";
+ double ration = (double) replicationCount / totalCount * 100d;
+ return NumberFormat.getInstance().format(ration) + "%";
}
/**
@@ -773,7 +783,7 @@
Configuration.CacheMode cacheMode = configuration.getCacheMode();
if (!cacheMode.equals(Configuration.CacheMode.LOCAL) && configuration.getCacheMode().isSynchronous())
{
- ProtocolStack stack = ((JChannel)channel).getProtocolStack();
+ ProtocolStack stack = ((JChannel) channel).getProtocolStack();
TP transport = stack.getTransport();
if (transport.isEnableBundling())
{
@@ -784,7 +794,7 @@
//bundling is good for async caches
if (!cacheMode.isSynchronous())
{
- ProtocolStack stack = ((JChannel)channel).getProtocolStack();
+ ProtocolStack stack = ((JChannel) channel).getProtocolStack();
TP transport = stack.getTransport();
if (!transport.isEnableBundling())
{
Modified: core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -245,8 +245,14 @@
@Override
public void addChild(InternalNode<K, V> child)
{
- Fqn childFqn = child.getFqn();
- if (childFqn.isDirectChildOf(fqn))
+ addChild(child, false);
+ }
+
+ @Override
+ public void addChild(InternalNode<K, V> child, boolean safe)
+ {
+ Fqn<?> childFqn = child.getFqn();
+ if (safe || childFqn.isDirectChildOf(fqn))
{
children().put(childFqn.getLastElement(), child);
}
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeFactory.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeFactory.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -22,7 +22,7 @@
public class MVCCNodeFactory<K, V> extends AbstractNodeFactory<K, V>
{
private boolean useRepeatableRead;
- private static final NullMarkerNode NULL_MARKER = new NullMarkerNode(null);
+ private static final NullMarkerNode NULL_MARKER = new NullMarkerNode();
private static final Log log = LogFactory.getLog(MVCCNodeFactory.class);
private static final boolean trace = log.isTraceEnabled();
private boolean lockChildForInsertRemove;
@@ -48,10 +48,10 @@
*/
@Override
@SuppressWarnings("unchecked")
- public ReadCommittedNode createWrappedNode(InternalNode<K, V> node)
+ public ReadCommittedNode createWrappedNode(InternalNode<K, V> node, InternalNode<K, V> parent)
{
if (node == null) return useRepeatableRead ? NULL_MARKER : null;
- ReadCommittedNode rcn = useRepeatableRead ? new RepeatableReadNode(node) : new ReadCommittedNode(node);
+ ReadCommittedNode rcn = useRepeatableRead ? new RepeatableReadNode(node, parent) : new ReadCommittedNode(node, parent);
rcn.initialize(configuration, invocationContextContainer, componentRegistry, interceptorChain);
rcn.injectDependencies(cache);
return rcn;
@@ -73,7 +73,7 @@
@SuppressWarnings("unchecked")
public NodeSPI<K, V> createRootNode()
{
- return createWrappedNode(createInternalNode(Fqn.ROOT));
+ return createWrappedNode(createInternalNode(Fqn.ROOT), null);
}
@Override
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeHelper.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeHelper.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/MVCCNodeHelper.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -66,8 +66,8 @@
* Attempts to provide the context with a set of wrapped nodes based on the Collection of fqns passed in. If the nodes
* already exist in the context then the node is not wrapped again.
* <p/>
- * {@link InternalNode}s are wrapped using {@link org.jboss.cache.NodeFactory#createWrappedNode(org.jboss.cache.InternalNode)}
- * and as such, null internal nodes are treated according to isolation level used. See {@link org.jboss.cache.NodeFactory#createWrappedNode(org.jboss.cache.InternalNode)}
+ * {@link InternalNode}s are wrapped using {@link org.jboss.cache.NodeFactory#createWrappedNode(org.jboss.cache.InternalNode, org.jboss.cache.InternalNode)}
+ * and as such, null internal nodes are treated according to isolation level used. See {@link org.jboss.cache.NodeFactory#createWrappedNode(org.jboss.cache.InternalNode, org.jboss.cache.InternalNode)}
* for details on this behaviour.
* <p/>
* Note that if the context has the {@link org.jboss.cache.config.Option#isForceWriteLock()} option set, then write locks are
@@ -113,8 +113,8 @@
{
if (trace) log.trace("Node " + f + " is not in context, fetching from container.");
// simple implementation. Peek the node, wrap it, put wrapped node in the context.
- InternalNode node = dataContainer.peekInternalNode(f, false);
- ReadCommittedNode wrapped = nodeFactory.createWrappedNode(node);
+ InternalNode[] nodes = dataContainer.peekInternalNodeAndDirectParent(f, false);
+ ReadCommittedNode wrapped = nodeFactory.createWrappedNode(nodes[0], nodes[1]); // even though parents aren't needed for reading, we hold on to this ref in case the node is later written to.
if (wrapped != null) ctx.putLookedUpNode(f, wrapped);
return wrapped;
}
@@ -170,10 +170,10 @@
* @throws InterruptedException if interrupted
*/
@SuppressWarnings("unchecked")
- public NodeSPI wrapNodeForWriting(InvocationContext context, Fqn fqn, boolean lockForWriting, boolean createIfAbsent, boolean includeInvalidNodes, boolean forRemoval, boolean force) throws InterruptedException
+ public ReadCommittedNode wrapNodeForWriting(InvocationContext context, Fqn fqn, boolean lockForWriting, boolean createIfAbsent, boolean includeInvalidNodes, boolean forRemoval, boolean force) throws InterruptedException
{
Fqn parentFqn = null;
- NodeSPI n = context.lookUpNode(fqn);
+ ReadCommittedNode n = (ReadCommittedNode) context.lookUpNode(fqn);
if (createIfAbsent && n != null && n.isNullNode()) n = null;
if (n != null) // exists in context! Just acquire lock if needed, and wrap.
{
@@ -194,7 +194,8 @@
else
{
// else, fetch from dataContainer.
- InternalNode in = dataContainer.peekInternalNode(fqn, includeInvalidNodes);
+ InternalNode[] nodes = dataContainer.peekInternalNodeAndDirectParent(fqn, includeInvalidNodes);
+ InternalNode in = nodes[0];
if (in != null)
{
// exists in cache! Just acquire lock if needed, and wrap.
@@ -204,7 +205,7 @@
{
needToCopy = true;
}
- n = nodeFactory.createWrappedNode(in);
+ n = nodeFactory.createWrappedNode(in, nodes[1]);
context.putLookedUpNode(fqn, n);
if (needToCopy) n.markForUpdate(dataContainer, writeSkewCheck);
}
@@ -225,7 +226,7 @@
acquireLock(context, fqn);
in = nodeFactory.createChildNode(fqn, null, context, false);
- n = nodeFactory.createWrappedNode(in);
+ n = nodeFactory.createWrappedNode(in, parent.getDelegationTarget());
n.setCreated(true);
context.putLookedUpNode(fqn, n);
n.markForUpdate(dataContainer, writeSkewCheck);
@@ -255,7 +256,7 @@
* @throws InterruptedException if interrupted
*/
@SuppressWarnings("unchecked")
- public NodeSPI wrapNodeForWriting(InvocationContext context, InternalNode node) throws InterruptedException
+ public NodeSPI wrapNodeForWriting(InvocationContext context, InternalNode node, InternalNode parent) throws InterruptedException
{
Fqn fqn = node.getFqn();
NodeSPI n = context.lookUpNode(fqn);
@@ -278,7 +279,7 @@
{
needToCopy = true;
}
- n = nodeFactory.createWrappedNode(node);
+ n = nodeFactory.createWrappedNode(node, parent);
context.putLookedUpNode(fqn, n);
if (needToCopy) n.markForUpdate(dataContainer, writeSkewCheck);
}
@@ -361,12 +362,13 @@
if (fqnList != null) fqnList.add(fqn);
// now wrap and add to the context
- NodeSPI rcn = wrapNodeForWriting(ctx, fqn, true, false, true, false, false);
+ ReadCommittedNode rcn = wrapNodeForWriting(ctx, fqn, true, false, true, false, false);
if (rcn != null)
{
rcn.markForUpdate(dataContainer, writeSkewCheck);
Map<Object, InternalNode<?, ?>> children = rcn.getDelegationTarget().getChildrenMap();
- for (InternalNode child : children.values()) lockForWritingRecursive(child, ctx, fqnList);
+ for (InternalNode child : children.values())
+ lockForWritingRecursive(child, rcn.getInternalParent(), ctx, fqnList);
}
}
@@ -380,19 +382,19 @@
* @throws InterruptedException if interrupted
*/
@SuppressWarnings("unchecked")
- private void lockForWritingRecursive(InternalNode node, InvocationContext ctx, List<Fqn> fqnList) throws InterruptedException
+ private void lockForWritingRecursive(InternalNode node, InternalNode parent, InvocationContext ctx, List<Fqn> fqnList) throws InterruptedException
{
Fqn fqn = node.getFqn();
acquireLock(ctx, fqn); // lock node
if (fqnList != null) fqnList.add(fqn);
// now wrap and add to the context
- NodeSPI rcn = wrapNodeForWriting(ctx, node);
+ NodeSPI rcn = wrapNodeForWriting(ctx, node, parent);
if (rcn != null)
{
rcn.markForUpdate(dataContainer, writeSkewCheck);
- Map<Object, InternalNode<?, ?>> children = rcn.getDelegationTarget().getChildrenMap();
- for (InternalNode child : children.values()) lockForWritingRecursive(child, ctx, fqnList);
+ Map<Object, InternalNode<?, ?>> children = node.getChildrenMap();
+ for (InternalNode child : children.values()) lockForWritingRecursive(child, node, ctx, fqnList);
}
}
@@ -413,8 +415,8 @@
ReadCommittedNode node = (ReadCommittedNode) ctx.lookUpNode(fqn);
if (node == null)
{
- InternalNode in = dataContainer.peekInternalNode(fqn, false);
- node = nodeFactory.createWrappedNode(in);
+ InternalNode[] nodes = dataContainer.peekInternalNodeAndDirectParent(fqn, false);
+ node = nodeFactory.createWrappedNode(nodes[0], nodes[1]);
ctx.putLookedUpNode(fqn, node);
}
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -136,6 +136,11 @@
delegate.addChild(child);
}
+ public final void addChild(InternalNode<K, V> child, boolean safe)
+ {
+ delegate.addChild(child, safe);
+ }
+
public final V remove(K key)
{
return delegate.remove(key);
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/NullMarkerNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/NullMarkerNode.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/NullMarkerNode.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -1,7 +1,6 @@
package org.jboss.cache.mvcc;
import org.jboss.cache.DataContainer;
-import org.jboss.cache.InternalNode;
/**
* A marker node to represent a null node for repeatable read, so that a read that returns a null can continue to return
@@ -12,9 +11,9 @@
*/
public class NullMarkerNode extends RepeatableReadNode
{
- public NullMarkerNode(InternalNode node)
+ public NullMarkerNode()
{
- super(node);
+ super(null, null);
}
/**
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -24,7 +24,11 @@
protected volatile InternalNode backup;
protected byte flags = 0;
+ protected Fqn fqn;
+ protected InternalNode parent;
+ protected Fqn parentFqn;
+
protected static enum Flags
{
CHANGED(0x1), CREATED(0x2), DELETED(0x4);
@@ -37,11 +41,18 @@
}
@SuppressWarnings("unchecked")
- public ReadCommittedNode(InternalNode node)
+ public ReadCommittedNode(InternalNode node, InternalNode parent)
{
super(node);
+ this.parent = parent;
+ if (parent != null) parentFqn = parent.getFqn();
}
+ public InternalNode getInternalParent()
+ {
+ return parent;
+ }
+
/**
* Tests whether a flag is set.
*
@@ -79,6 +90,13 @@
return false;
}
+ // convenience fqn retrieval method
+ protected final Fqn fqn()
+ {
+ if (fqn == null) fqn = getFqn();
+ return fqn;
+ }
+
@Override
public void markForUpdate(DataContainer container, boolean writeSkewCheck)
{
@@ -101,7 +119,7 @@
// only do stuff if there are changes.
if (isFlagSet(CHANGED))
{
- Fqn fqn = getFqn();
+ Fqn fqn = fqn();
if (trace)
log.trace("Updating node [" + fqn + "]. deleted=" + isDeleted() + " valid=" + isValid() + " changed=" + isChanged() + " created=" + isFlagSet(CREATED));
@@ -125,7 +143,7 @@
{
// add newly created nodes to parents.
InternalNode parent = lookupParent(fqn, ctx, container);
- parent.addChild(node);
+ parent.addChild(node, true); // we know this is safe since we calculated the parent from the child. No need to have the parent re-do checks when adding the child again.
}
else
{
@@ -156,8 +174,10 @@
*/
protected final InternalNode lookupParent(Fqn fqn, InvocationContext ctx, DataContainer container) throws NodeNotExistsException
{
+ if (parent != null) return parent;
+
InternalNode retval;
- Fqn parentFqn = fqn.getParent();
+ Fqn parentFqn = this.parentFqn == null ? fqn.getParent() : this.parentFqn; // use the class-level parentFqn where possible since this will already have a hashcode computed.
NodeSPI parent = ctx.lookUpNode(parentFqn);
// first check if the parent is cached in the context.
if (parent != null)
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java 2008-09-18 11:01:52 UTC (rev 6748)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java 2008-09-18 11:02:45 UTC (rev 6749)
@@ -6,7 +6,6 @@
import org.jboss.cache.Fqn;
import org.jboss.cache.InternalNode;
import org.jboss.cache.InvocationContext;
-
import static org.jboss.cache.mvcc.ReadCommittedNode.Flags.CHANGED;
import static org.jboss.cache.mvcc.ReadCommittedNode.Flags.DELETED;
import org.jboss.cache.optimistic.DataVersioningException;
@@ -21,9 +20,9 @@
{
private static final Log log = LogFactory.getLog(RepeatableReadNode.class);
- public RepeatableReadNode(InternalNode node)
+ public RepeatableReadNode(InternalNode node, InternalNode parent)
{
- super(node);
+ super(node, parent);
}
@Override
@@ -31,7 +30,7 @@
{
if (isFlagSet(CHANGED)) return; // already copied
- Fqn fqn = getFqn();
+ Fqn fqn = fqn();
// mark node as changed.
setFlag(CHANGED);
@@ -58,7 +57,7 @@
@SuppressWarnings("unchecked")
protected void updateNode(InvocationContext ctx, DataContainer dataContainer)
{
- Fqn fqn = getFqn();
+ Fqn fqn = fqn();
if (fqn.isRoot())
{
dataContainer.setRoot(node);
@@ -66,7 +65,7 @@
else if (!isFlagSet(DELETED))
{
InternalNode parent = lookupParent(fqn, ctx, dataContainer);
- parent.addChild(node);
+ parent.addChild(node, true); // we know this is safe since we calculated the parent from the child. No need to have the parent re-do checks when adding the child again.
}
}
}
More information about the jbosscache-commits
mailing list