JBoss Cache SVN: r6131 - in searchable/trunk: src/main/java/org/jboss/cache/search and 2 other directories.
by jbosscache-commits@lists.jboss.org
Author: navssurtani
Date: 2008-06-30 15:22:09 -0400 (Mon, 30 Jun 2008)
New Revision: 6131
Modified:
searchable/trunk/pom.xml
searchable/trunk/src/main/java/org/jboss/cache/search/CacheEntityId.java
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java
searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalCacheTest.java
searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java
Log:
Modified: searchable/trunk/pom.xml
===================================================================
--- searchable/trunk/pom.xml 2008-06-30 19:10:15 UTC (rev 6130)
+++ searchable/trunk/pom.xml 2008-06-30 19:22:09 UTC (rev 6131)
@@ -39,7 +39,7 @@
<dependency>
<groupId>org.hibernate.sandbox</groupId>
<artifactId>hibernate-search-gsoc</artifactId>
- <version>3.1.0-SNAPSHOT</version>
+ <version>3.1.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -54,6 +54,13 @@
<version>1.4.2</version>
</dependency>
+ <dependency>
+ <groupId>org.hibernate.apache.lucene.solr</groupId>
+ <artifactId>apache-solr-analyzer</artifactId>
+ <version>1.2.0</version>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
<build>
<plugins>
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/CacheEntityId.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/CacheEntityId.java 2008-06-30 19:10:15 UTC (rev 6130)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/CacheEntityId.java 2008-06-30 19:22:09 UTC (rev 6131)
@@ -69,9 +69,8 @@
public String getDocumentId()
{
- if (key != null || fqn != null)
+ if (key == null || fqn == null)
{
-
throw new IllegalArgumentException("Either your key or fqn is null. Please check again.");
}
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java 2008-06-30 19:10:15 UTC (rev 6130)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheFactory.java 2008-06-30 19:22:09 UTC (rev 6131)
@@ -51,16 +51,18 @@
if (log.isWarnEnabled()) log.warn("You haven't passed in any classes to index. Is this an error?");
}
- // Step 1: Add cache listener to listen for events happening in the cache.
- SearchableListener listener = new SearchableListener();
- c.addCacheListener(listener);
-
- // step 2: create hibernate search searchImpl
+ // step 1: create hibernate search searchImpl
Cfg cfg = new SearchableCacheCfgImpl(classes, properties);
// set classes in the cfg
SearchFactoryImpl searchImpl = new SearchFactoryImpl(cfg);
+
+ // Step 2: Add cache listener to listen for events happening in the cache.
+ SearchableListener listener = new SearchableListener(searchImpl);
+ c.addCacheListener(listener);
+
+
// step 3: create the searchable cache delegate.
SearchableCache sc = new SearchableCacheImpl(c, searchImpl);
return sc;
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java 2008-06-30 19:10:15 UTC (rev 6130)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/SearchableListener.java 2008-06-30 19:22:09 UTC (rev 6131)
@@ -12,8 +12,8 @@
/**
* @author Navin Surtani - navin(a)surtani.org
- *
- * Class that listens for changes made to the cache so that the Lucene indexes can be updated.
+ * <p/>
+ * Class that listens for changes made to the cache so that the Lucene indexes can be updated.
*/
@CacheListener
@@ -21,10 +21,14 @@
{
private SearchFactoryImpl searchFactory;
+ public SearchableListener(SearchFactoryImpl searchFactory)
+ {
+ this.searchFactory = searchFactory;
+ }
+
/**
* Takes in a NodeModifiedEvent and updates the Lucene indexes using methods on the NodeModifiedEvent class.
*
- *
* @param event that has occured - or a node that has been changed. {@link org.jboss.cache.notifications.event.NodeModifiedEvent}
*/
@@ -72,7 +76,7 @@
/**
* If the modification type is DELETE_DATA then this method will be called.
* Takes in the event as a parameter
- *
+ *
* @param event that has occured - or a node that has been changed. {@link org.jboss.cache.notifications.event.NodeModifiedEvent}
*/
void handleDeleteData(NodeModifiedEvent event)
Modified: searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalCacheTest.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalCacheTest.java 2008-06-30 19:10:15 UTC (rev 6130)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalCacheTest.java 2008-06-30 19:22:09 UTC (rev 6131)
@@ -68,7 +68,7 @@
public void testSimple() throws ParseException
{
- queryParser = new QueryParser("field", new StandardAnalyzer());
+ queryParser = new QueryParser("blurb", new StandardAnalyzer());
luceneQuery = queryParser.parse("playing");
cacheQuery = searchableCache.createQuery(luceneQuery);
@@ -80,6 +80,8 @@
public void testMultipleResults() throws ParseException
{
+ queryParser = new QueryParser("name", new StandardAnalyzer());
+
luceneQuery = queryParser.parse("Goat");
cacheQuery = searchableCache.createQuery(luceneQuery);
found = cacheQuery.list();
@@ -92,7 +94,7 @@
public void testModified() throws ParseException
{
- queryParser = new QueryParser("field", new StandardAnalyzer());
+ queryParser = new QueryParser("blurb", new StandardAnalyzer());
luceneQuery = queryParser.parse("playing");
cacheQuery = searchableCache.createQuery(luceneQuery);
@@ -116,6 +118,8 @@
public void testAdded() throws ParseException
{
+ queryParser = new QueryParser("name", new StandardAnalyzer());
+
luceneQuery = queryParser.parse("Goat");
cacheQuery = searchableCache.createQuery(luceneQuery);
found = cacheQuery.list();
@@ -142,6 +146,8 @@
public void testRemoved() throws ParseException
{
+ queryParser = new QueryParser("name", new StandardAnalyzer());
+
luceneQuery = queryParser.parse("Goat");
cacheQuery = searchableCache.createQuery(luceneQuery);
found = cacheQuery.list();
Modified: searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java 2008-06-30 19:10:15 UTC (rev 6130)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/test/Person.java 2008-06-30 19:22:09 UTC (rev 6131)
@@ -2,10 +2,12 @@
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
+import org.hibernate.search.annotations.ProvidedId;
/**
* @author Navin Surtani - navin(a)surtani.org
*/
+@ProvidedId
@Indexed
public class Person
{
16 years, 2 months
JBoss Cache SVN: r6130 - core/branches/2.2.X/src/main/java/org/jboss/cache/factories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2008-06-30 15:10:15 -0400 (Mon, 30 Jun 2008)
New Revision: 6130
Modified:
core/branches/2.2.X/src/main/java/org/jboss/cache/factories/XmlConfigurationParser.java
Log:
PMD fixes
Modified: core/branches/2.2.X/src/main/java/org/jboss/cache/factories/XmlConfigurationParser.java
===================================================================
--- core/branches/2.2.X/src/main/java/org/jboss/cache/factories/XmlConfigurationParser.java 2008-06-30 19:07:05 UTC (rev 6129)
+++ core/branches/2.2.X/src/main/java/org/jboss/cache/factories/XmlConfigurationParser.java 2008-06-30 19:10:15 UTC (rev 6130)
@@ -347,7 +347,10 @@
}
catch (Exception e)
{
- throw new ConfigurationException("Bad buddyCommunicationTimeout [" + strBuddyCommunicationTimeout + "]");
+ if (strBuddyCommunicationTimeout != null && strBuddyCommunicationTimeout.trim().length() != 0)
+ {
+ throw new ConfigurationException("Bad buddyCommunicationTimeout [" + strBuddyCommunicationTimeout + "]");
+ }
}
finally
{
16 years, 2 months
JBoss Cache SVN: r6129 - in core/trunk/src: main/java/org/jboss/cache/commands/write and 6 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2008-06-30 15:07:05 -0400 (Mon, 30 Jun 2008)
New Revision: 6129
Added:
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadTestBase.java
Modified:
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/NodeFactory.java
core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
core/trunk/src/main/java/org/jboss/cache/commands/write/EvictCommand.java
core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactoryImpl.java
core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java
core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java
core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java
core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewLockTest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewWithParentLockTest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewLockTest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewWithParentLockTest.java
core/trunk/src/test/java/org/jboss/cache/commands/write/EvictCommandTest.java
Log:
More MVCC work
Modified: core/trunk/src/main/java/org/jboss/cache/DataContainer.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainer.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -144,7 +144,7 @@
/**
* Evicts the given node. If recursive is set to true then all child nodes are recusively evicted.
*/
- void evict(Fqn fqn, boolean recursive);
+ void evict(Fqn fqn, boolean recursive); // TODO: See if this is still needed here
/**
* <pre>
@@ -157,7 +157,7 @@
* @return true if the FQN is leaf and was removed; false if is an intermediate FQN and only contained data
* is droped.
*/
- boolean evict(Fqn fqn);
+ boolean evict(Fqn fqn); // TODO: See if this is still needed here
/**
* Traverses the tree to the given Fqn, creating nodes if needed. Returns a list of nodes created, as well as a reference to the last node.
@@ -177,10 +177,11 @@
/**
* Similar to {@link #peek(Fqn)} except that the underlying node is NOT wrapped as a {@link org.jboss.cache.NodeSPI}.
*
- * @param f fqn to peek
+ * @param f fqn to peek
+ * @param includeInvalidNodes if true, invalid nodes will be considered as well.
* @return internal node
*/
- InternalNode peekInternalNode(Fqn f);
+ InternalNode peekInternalNode(Fqn f, boolean includeInvalidNodes);
/**
* Sets a new root node
Modified: core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/DataContainerImpl.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -424,7 +424,7 @@
}
}
- protected void removeData(Fqn fqn)
+ private void removeData(Fqn fqn)
{
NodeSPI n = peek(fqn);
if (n == null)
@@ -465,10 +465,10 @@
return new Object[]{result, n};
}
- public InternalNode peekInternalNode(Fqn f)
+ public InternalNode peekInternalNode(Fqn f, boolean includeInvalidNodes)
{
// Yuck!
- NodeSPI nodeSPI = peek(f);
+ NodeSPI nodeSPI = peek(f, false, includeInvalidNodes);
if (nodeSPI == null) return null;
return (InternalNode) ((NodeInvocationDelegate) nodeSPI).getDelegationTarget();
}
Modified: core/trunk/src/main/java/org/jboss/cache/NodeFactory.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/NodeFactory.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/NodeFactory.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -15,8 +15,11 @@
import org.jboss.cache.interceptors.InterceptorChain;
import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.invocation.NodeInvocationDelegate;
+import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.lock.LockStrategyFactory;
import org.jboss.cache.mvcc.InternalNode;
+import org.jboss.cache.mvcc.ReadCommittedNode;
+import org.jboss.cache.mvcc.RepeatableReadNode;
import org.jboss.cache.optimistic.TransactionWorkspace;
import org.jboss.cache.optimistic.WorkspaceNode;
import org.jboss.cache.optimistic.WorkspaceNodeImpl;
@@ -37,6 +40,7 @@
private InterceptorChain interceptorChain;
private CommandsFactory commandsFactory;
private LockStrategyFactory lockStrategyFactory;
+ private boolean useRepeatableRead;
@Override
protected <T> T construct(Class<T> componentType)
@@ -44,6 +48,21 @@
throw new UnsupportedOperationException("Should never be called!");
}
+ /**
+ * Creates an MVCC wrapped node - either a {@link org.jboss.cache.mvcc.ReadCommittedNode} or it's subclass, a
+ * {@link org.jboss.cache.mvcc.RepeatableReadNode} based on cache configuration.
+ *
+ * @param node internal node to wrap.
+ * @return a ReadCommittedNode
+ */
+ public ReadCommittedNode createMvccNode(InternalNode node)
+ {
+ ReadCommittedNode rcn = useRepeatableRead ? new RepeatableReadNode(node) : new ReadCommittedNode(node);
+ rcn.initialize(configuration, invocationContextContainer, componentRegistry, interceptorChain);
+ rcn.injectDependencies(cache);
+ return rcn;
+ }
+
public enum NodeType
{
UNVERSIONED_NODE, VERSIONED_NODE, WORKSPACE_NODE
@@ -82,6 +101,7 @@
public void init()
{
useVersionedNode = configuration.getNodeLockingScheme() != NodeLockingScheme.PESSIMISTIC;
+ useRepeatableRead = configuration.getIsolationLevel() == IsolationLevel.REPEATABLE_READ;
}
Modified: core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -525,8 +525,13 @@
public void setChildrenMapDirect(Map<Object, Node<K, V>> children)
{
- this.children().clear();
- this.children.putAll(children);
+ if (children == null)
+ this.children = null;
+ else
+ {
+ this.children().clear();
+ this.children.putAll(children);
+ }
}
public void putAll(Map data)
@@ -552,7 +557,8 @@
// versioning
- public void setVersion(DataVersion version)
+ public void setVersion(DataVersion
+ version)
{
throw new UnsupportedOperationException("Versioning not supported");
}
Modified: core/trunk/src/main/java/org/jboss/cache/commands/write/EvictCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/write/EvictCommand.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/commands/write/EvictCommand.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -1,5 +1,7 @@
package org.jboss.cache.commands.write;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.jboss.cache.DataContainer;
import org.jboss.cache.Fqn;
import org.jboss.cache.NodeSPI;
@@ -8,6 +10,8 @@
import org.jboss.cache.invocation.InvocationContext;
import org.jboss.cache.notifications.Notifier;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -24,6 +28,10 @@
private boolean recursive = false;
protected Notifier notifier;
+ private static final Log log = LogFactory.getLog(EvictCommand.class);
+ private static final boolean trace = log.isTraceEnabled();
+ private boolean isUsingMvcc;
+ private List<Fqn> nodesToEvict;
public EvictCommand(Fqn fqn)
{
@@ -34,12 +42,23 @@
{
}
- public void initialize(Notifier notifier, DataContainer dataContainer)
+ public void initialize(Notifier notifier, DataContainer dataContainer, boolean isUsingMvcc)
{
super.initialize(dataContainer);
this.notifier = notifier;
+ this.isUsingMvcc = isUsingMvcc;
}
+ public List<Fqn> getNodesToEvict()
+ {
+ return nodesToEvict;
+ }
+
+ public void setNodesToEvict(List<Fqn> nodesToEvict)
+ {
+ this.nodesToEvict = nodesToEvict;
+ }
+
/**
* Evicts a node.
* <p/>
@@ -50,9 +69,8 @@
*/
public Object perform(InvocationContext ctx)
{
- //NodeSPI node = ctx.lookUpNode(fqn);
- // TODO: MVCC - eviction actually needs to look at invalid nodes (tombstones) as well.
- NodeSPI node = dataContainer.peek(fqn, false, true);
+ // TODO: remove this ugly hack
+ NodeSPI node = lookupForEviction(ctx, fqn);
if (node == null)
{
return false;
@@ -63,25 +81,61 @@
}
else if (recursive)
{
- List<Fqn> nodesToEvict = dataContainer.getNodesForEviction(fqn, true);
- for (Fqn aFqn : nodesToEvict)
+ Collection<Fqn> nodesToEvict = getRecursiveEvictionNodes();
+
+ if (nodesToEvict != null)
{
- evictNode(aFqn, ctx);
+ for (Fqn aFqn : nodesToEvict)
+ {
+ evictNode(aFqn, ctx, lookupForEviction(ctx, aFqn));
+ }
}
return !nodesToEvict.isEmpty();
}
else
{
- return evictNode(fqn, ctx);
+ return evictNode(fqn, ctx, node);
}
}
- boolean evictNode(Fqn fqn, InvocationContext ctx)
+ private Collection<Fqn> getRecursiveEvictionNodes()
{
+ if (isUsingMvcc)
+ {
+ Collections.sort(nodesToEvict);
+ Collections.reverse(nodesToEvict);
+ return nodesToEvict;
+ }
+ else
+ return dataContainer.getNodesForEviction(fqn, true);
+ }
+
+ boolean evictNode(Fqn fqn, InvocationContext ctx, NodeSPI node)
+ {
notifier.notifyNodeEvicted(fqn, true, ctx);
try
{
- return dataContainer.evict(fqn);
+ if (node == null) return true;
+ if (node.hasChildrenDirect())
+ {
+ if (trace) log.trace("removing DATA as node has children: evict(" + fqn + ")");
+ node.clearDataDirect();
+ node.setDataLoaded(false);
+ return false;
+ }
+ else
+ {
+ if (trace) log.trace("removing NODE as it is a leaf: evict(" + fqn + ")");
+ NodeSPI parentNode = lookupForEviction(ctx, fqn.getParent());
+
+ if (parentNode != null)
+ {
+ parentNode.removeChildDirect(fqn.getLastElement());
+ parentNode.setChildrenLoaded(false);
+ }
+ node.setValid(false, false);
+ return true;
+ }
}
finally
{
@@ -89,6 +143,19 @@
}
}
+ private NodeSPI lookupForEviction(InvocationContext ctx, Fqn fqn)
+ {
+ // TODO: do something about this nasty hack
+ if (isUsingMvcc)
+ {
+ return ctx.lookUpNode(fqn);
+ }
+ else
+ {
+ return dataContainer.peek(fqn, false, true);
+ }
+ }
+
public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
{
return visitor.visitEvictFqnCommand(ctx, this);
Modified: core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactoryImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactoryImpl.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/factories/CommandsFactoryImpl.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -28,10 +28,21 @@
import org.jboss.cache.commands.tx.OptimisticPrepareCommand;
import org.jboss.cache.commands.tx.PrepareCommand;
import org.jboss.cache.commands.tx.RollbackCommand;
-import org.jboss.cache.commands.write.*;
+import org.jboss.cache.commands.write.ClearDataCommand;
+import org.jboss.cache.commands.write.CreateNodeCommand;
+import org.jboss.cache.commands.write.EvictCommand;
+import org.jboss.cache.commands.write.InvalidateCommand;
+import org.jboss.cache.commands.write.MoveCommand;
+import org.jboss.cache.commands.write.PutDataMapCommand;
+import org.jboss.cache.commands.write.PutForExternalReadCommand;
+import org.jboss.cache.commands.write.PutKeyValueCommand;
+import org.jboss.cache.commands.write.RemoveKeyCommand;
+import org.jboss.cache.commands.write.RemoveNodeCommand;
+import org.jboss.cache.commands.write.VersionedInvalidateCommand;
import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.factories.annotations.NonVolatile;
+import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.interceptors.InterceptorChain;
import org.jboss.cache.notifications.Notifier;
import org.jboss.cache.transaction.GlobalTransaction;
@@ -46,7 +57,6 @@
/**
* This is the implementation to use for most commands and most locking schemes.
*/
-@NonVolatile
public class CommandsFactoryImpl implements CommandsFactory
{
protected RPCManager rpcManager;
@@ -59,6 +69,7 @@
protected Configuration configuration;
protected TransactionManager txManager;
protected BuddyFqnTransformer buddyFqnTransformer;
+ private boolean usingMvcc;
public CommandsFactoryImpl()
{
@@ -81,6 +92,12 @@
this.buddyFqnTransformer = buddyFqnTransformer;
}
+ @Start
+ public void start()
+ {
+ usingMvcc = configuration.getNodeLockingScheme() == NodeLockingScheme.MVCC;
+ }
+
public PutDataMapCommand buildPutDataMapCommand(GlobalTransaction gtx, Fqn fqn, Map data)
{
PutDataMapCommand cmd = new PutDataMapCommand(gtx, fqn, data);
@@ -148,7 +165,7 @@
public EvictCommand buildEvictFqnCommand(Fqn fqn)
{
EvictCommand command = new EvictCommand(fqn);
- command.initialize(notifier, dataContainer);
+ command.initialize(notifier, dataContainer, usingMvcc);
return command;
}
Modified: core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/factories/PessimisticCommandsFactoryImpl.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -18,7 +18,6 @@
import org.jboss.cache.commands.write.PutKeyValueCommand;
import org.jboss.cache.commands.write.RemoveKeyCommand;
import org.jboss.cache.commands.write.RemoveNodeCommand;
-import org.jboss.cache.factories.annotations.NonVolatile;
import org.jboss.cache.transaction.GlobalTransaction;
import java.util.Map;
@@ -31,7 +30,6 @@
* @see org.jboss.cache.commands.pessimistic.ReversibleCommand
* @since 3.0
*/
-@NonVolatile
public class PessimisticCommandsFactoryImpl extends CommandsFactoryImpl
{
@Override
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/InvocationContextInterceptor.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -176,6 +176,7 @@
}
finally
{
+ // TODO: scope upgrading should happen transparently
/*
* we should scrub txs after every call to prevent race conditions
* basically any other call coming in on the same thread and hijacking any running tx's
@@ -204,6 +205,9 @@
// reset the context to prevent leakage of internals
ctx.setCommand(null);
ctx.setMethodCall(null);
+
+
+ ctx.reset();
}
}
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -14,22 +14,31 @@
import org.jboss.cache.commands.read.GravitateDataCommand;
import org.jboss.cache.commands.tx.CommitCommand;
import org.jboss.cache.commands.tx.RollbackCommand;
-import org.jboss.cache.commands.write.*;
+import org.jboss.cache.commands.write.ClearDataCommand;
+import org.jboss.cache.commands.write.CreateNodeCommand;
+import org.jboss.cache.commands.write.EvictCommand;
+import org.jboss.cache.commands.write.InvalidateCommand;
+import org.jboss.cache.commands.write.MoveCommand;
+import org.jboss.cache.commands.write.PutDataMapCommand;
+import org.jboss.cache.commands.write.PutForExternalReadCommand;
+import org.jboss.cache.commands.write.PutKeyValueCommand;
+import org.jboss.cache.commands.write.RemoveKeyCommand;
+import org.jboss.cache.commands.write.RemoveNodeCommand;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.Start;
import org.jboss.cache.interceptors.base.PostProcessingCommandInterceptor;
import org.jboss.cache.invocation.InvocationContext;
import org.jboss.cache.invocation.NodeInvocationDelegate;
-import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.lock.LockManager;
import static org.jboss.cache.lock.LockType.WRITE;
import org.jboss.cache.mvcc.InternalNode;
import org.jboss.cache.mvcc.ReadCommittedNode;
-import org.jboss.cache.mvcc.RepeatableReadNode;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
/**
* Interceptor to implement <a href="http://wiki.jboss.org/wiki/JBossCacheMVCC">MVCC</a> functionality.
@@ -48,7 +57,7 @@
// How will wrapper nodes unwrap?
- boolean isUsingRepeatableRead, ignoreWriteSkew, lockParentForChildInsertRemove;
+ boolean allowWriteSkew, lockParentForChildInsertRemove;
LockManager lockManager;
DataContainer dataContainer;
NodeFactory nodeFactory;
@@ -64,53 +73,133 @@
@Start
public void start()
{
- isUsingRepeatableRead = configuration.getIsolationLevel() == IsolationLevel.REPEATABLE_READ; // otherwise default to READ_COMMITTED
- ignoreWriteSkew = true; // todo this should come from a cfg variable
+ allowWriteSkew = configuration.isAllowWriteSkew();
lockParentForChildInsertRemove = configuration.isLockParentForChildInsertRemove();
}
@Override
public Object handlePutDataMapCommand(InvocationContext ctx, PutDataMapCommand command) throws Throwable
{
- getWrappedNode(ctx, command.getFqn(), true, true); // get the node and stick it in the context.
+ getWrappedNode(ctx, command.getFqn(), true, true, false); // get the node and stick it in the context.
return invokeNextInterceptor(ctx, command);
}
@Override
public Object handlePutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable
{
- getWrappedNode(ctx, command.getFqn(), true, true); // get the node and stick it in the context.
+ getWrappedNode(ctx, command.getFqn(), true, true, false); // get the node and stick it in the context.
return invokeNextInterceptor(ctx, command);
}
@Override
public Object handlePutForExternalReadCommand(InvocationContext ctx, PutForExternalReadCommand command) throws Throwable
{
- getWrappedNode(ctx, command.getFqn(), true, true); // get the node and stick it in the context.
+ getWrappedNode(ctx, command.getFqn(), true, true, false); // get the node and stick it in the context.
return invokeNextInterceptor(ctx, command);
}
@Override
public Object handleRemoveNodeCommand(InvocationContext ctx, RemoveNodeCommand command) throws Throwable
{
- // TODO : Handle this properly
- return handleWriteCommand(ctx, command, new ArrayList<Fqn>(1), Collections.singletonList(command.getFqn()));
+ // when removing a node we want to get a lock on the Fqn anyway and return the wrapped node.
+ Fqn nodeFqn = command.getFqn();
+
+ if (!nodeFqn.isRoot())
+ {
+ Fqn parentFqn = nodeFqn.getParent();
+ // inspect parent
+ InternalNode parent = dataContainer.peekInternalNode(parentFqn, false);
+ {
+ if (lockParentForChildInsertRemove || (parent != null && parent.isLockForChildInsertRemove()))
+ {
+ // lock parent
+ lockManager.lockAndRecord(parentFqn, WRITE, ctx);
+
+ // retrieve again from the dataContainer in case we have a race, and add to the context
+ getWrappedNode(ctx, parentFqn, true, false, false);
+ }
+ }
+ }
+
+ lockManager.lockAndRecord(nodeFqn, WRITE, ctx); // lock node.
+
+ // now wrap and add to the context
+ getWrappedNode(ctx, nodeFqn, true, false, false);
+
+ return invokeNextInterceptor(ctx, command);
}
@Override
public Object handleClearDataCommand(InvocationContext ctx, ClearDataCommand command) throws Throwable
{
- // TODO : Handle this properly
- return handleWriteCommand(ctx, command, new ArrayList<Fqn>(1), Collections.singletonList(command.getFqn()));
+ getWrappedNode(ctx, command.getFqn(), true, false, false);
+ return invokeNextInterceptor(ctx, command);
}
@Override
public Object handleEvictFqnCommand(InvocationContext ctx, EvictCommand command) throws Throwable
{
- // TODO : Handle this properly
- return handleWriteCommand(ctx, command, new ArrayList<Fqn>(1), Collections.singletonList(command.getFqn()));
+ // set lock acquisition timeout to 0 - we need to fail fast.
+ ctx.getOptionOverrides().setLockAcquisitionTimeout(0);
+
+ // similar to remove node, except that we need to take care of the recursive case.
+ Fqn nodeFqn = command.getFqn();
+
+ if (!nodeFqn.isRoot())
+ {
+ Fqn parentFqn = nodeFqn.getParent();
+ // inspect parent
+ InternalNode parent = dataContainer.peekInternalNode(parentFqn, true);
+ {
+ if (lockParentForChildInsertRemove || (parent != null && parent.isLockForChildInsertRemove()))
+ {
+ // lock parent
+ lockManager.lockAndRecord(parentFqn, WRITE, ctx);
+
+ // retrieve again from the dataContainer in case we have a race, and add to the context
+ ReadCommittedNode rcn = (ReadCommittedNode) getWrappedNode(ctx, parentFqn, true, false, false);
+ if (rcn != null) rcn.copyNodeForUpdate(dataContainer, allowWriteSkew);
+ }
+ }
+ }
+
+ List<Fqn> fqnsToEvict = command.isRecursive() ? new LinkedList<Fqn>() : null;
+
+ lockForEviction(nodeFqn, command.isRecursive(), ctx, fqnsToEvict);
+
+ if (fqnsToEvict != null) // add this set to the command
+ {
+ command.setNodesToEvict(fqnsToEvict);
+ }
+
+ return invokeNextInterceptor(ctx, command);
}
+ private void lockForEviction(Fqn fqn, boolean isRecursive, InvocationContext ctx, List<Fqn> fqnsToEvict) throws InterruptedException
+ {
+ lockManager.lockAndRecord(fqn, WRITE, ctx); // lock node.
+ if (fqnsToEvict != null) fqnsToEvict.add(fqn);
+
+ // now wrap and add to the context
+ ReadCommittedNode rcn = (ReadCommittedNode) getWrappedNode(ctx, fqn, true, false, true);
+ if (rcn != null)
+ {
+ rcn.copyNodeForUpdate(dataContainer, allowWriteSkew);
+
+ if (isRecursive)
+ {
+ Map<Object, NodeSPI> children = rcn.getChildrenMapDirect();
+ if (children != null)
+ {
+ for (NodeSPI child : children.values())
+ {
+ lockForEviction(child.getFqn(), isRecursive, ctx, fqnsToEvict);
+ }
+ }
+ }
+ }
+ }
+
@Override
public Object handleInvalidateCommand(InvocationContext ctx, InvalidateCommand command) throws Throwable
{
@@ -121,8 +210,8 @@
@Override
public Object handleRemoveKeyCommand(InvocationContext ctx, RemoveKeyCommand command) throws Throwable
{
- // TODO : Handle this properly
- return handleWriteCommand(ctx, command, new ArrayList<Fqn>(1), Collections.singletonList(command.getFqn()));
+ getWrappedNode(ctx, command.getFqn(), true, false, false);
+ return invokeNextInterceptor(ctx, command);
}
@Override
@@ -180,7 +269,7 @@
@Override
public Object handleCreateNodeCommand(InvocationContext ctx, CreateNodeCommand command) throws Throwable
{
- getWrappedNode(ctx, command.getFqn(), true, true); // get the node and stick it in the context.
+ getWrappedNode(ctx, command.getFqn(), true, true, false); // get the node and stick it in the context.
return invokeNextInterceptor(ctx, command);
}
@@ -232,7 +321,7 @@
{
// for each of these, swap refs
ReadCommittedNode rcn = (ReadCommittedNode) ctx.lookUpNode(fqnsToUnlock[i]);
- rcn.copyNodeForUpdate(dataContainer, ignoreWriteSkew);
+// rcn.copyNodeForUpdate(dataContainer, allowWriteSkew);
rcn.commitUpdate(dataContainer, nodeFactory);
// and then unlock
lockManager.unlock(fqnsToUnlock[i], owner);
@@ -261,7 +350,7 @@
if (commit)
{
// for each of these, swap refs
- rcn.copyNodeForUpdate(dataContainer, ignoreWriteSkew);
+// rcn.copyNodeForUpdate(dataContainer, allowWriteSkew);
rcn.commitUpdate(dataContainer, nodeFactory);
}
else
@@ -286,10 +375,10 @@
if (ctx.lookUpNode(f) == null)
{
// simple implementation. Peek the node, wrap it, put wrapped node in the context.
- InternalNode node = dataContainer.peekInternalNode(f);
+ InternalNode node = dataContainer.peekInternalNode(f, false);
if (node != null)
{
- NodeSPI wrapped = isUsingRepeatableRead ? new RepeatableReadNode(node) : new ReadCommittedNode(node);
+ NodeSPI wrapped = nodeFactory.createMvccNode(node);
ctx.putLookedUpNode(f, wrapped);
}
}
@@ -305,10 +394,10 @@
if (ctx.lookUpNode(f) == null)
{
// simple implementation. Peek the node, wrap it, put wrapped node in the context.
- InternalNode node = dataContainer.peekInternalNode(f);
+ InternalNode node = dataContainer.peekInternalNode(f, false);
if (node != null)
{
- NodeSPI wrapped = isUsingRepeatableRead ? new RepeatableReadNode(node) : new ReadCommittedNode(node);
+ NodeSPI wrapped = nodeFactory.createMvccNode(node);
ctx.putLookedUpNode(f, wrapped);
}
}
@@ -319,11 +408,11 @@
if (ctx.lookUpNode(f) == null)
{
// simple implementation. Peek the node, wrap it, put wrapped node in the context.
- InternalNode node = dataContainer.peekInternalNode(f);
+ InternalNode node = dataContainer.peekInternalNode(f, false);
if (node != null)
{
lockManager.lock(f, WRITE, ctx);
- NodeSPI wrapped = isUsingRepeatableRead ? new RepeatableReadNode(node) : new ReadCommittedNode(node);
+ NodeSPI wrapped = nodeFactory.createMvccNode(node);
ctx.putLookedUpNode(f, wrapped);
}
}
@@ -339,30 +428,43 @@
* data structure. It will lock the node, and potentially the parent as well, if necessary. If the parent is locked,
* it too will be added to the context if it wasn't there already.
*
- * @param fqn to retrieve
- * @param lock if true, a lock will be acquired.
- * @param createIfAbsent if true, will be created if absent.
+ * @param fqn to retrieve
+ * @param lockForWriting if true, a lock will be acquired.
+ * @param createIfAbsent if true, will be created if absent.
+ * @param includeInvalidNodes
* @return a NodeSPI or null.
*/
- protected NodeSPI getWrappedNode(InvocationContext context, Fqn fqn, boolean lock, boolean createIfAbsent) throws InterruptedException
+ protected NodeSPI getWrappedNode(InvocationContext context, Fqn fqn, boolean lockForWriting, boolean createIfAbsent, boolean includeInvalidNodes) throws InterruptedException
{
- NodeSPI n = context.lookUpNode(fqn);
+ ReadCommittedNode n = (ReadCommittedNode) context.lookUpNode(fqn);
if (n != null)
{
// acquire lock if needed
- if (lock && !isLocked(context, fqn)) lockManager.lockAndRecord(fqn, WRITE, context);
+ if (lockForWriting && !isLocked(context, fqn))
+ {
+ lockManager.lockAndRecord(fqn, WRITE, context);
+ // create a copy of the underlying node
+
+ n.copyNodeForUpdate(dataContainer, allowWriteSkew);
+ }
if (trace) log.trace("Retrieving wrapped node " + fqn);
return n;
}
// else, fetch from dataContainer.
- InternalNode in = dataContainer.peekInternalNode(fqn);
+ InternalNode in = dataContainer.peekInternalNode(fqn, includeInvalidNodes);
if (in != null)
{
// do we need a lock?
- if (lock && !isLocked(context, fqn)) lockManager.lockAndRecord(fqn, WRITE, context);
- NodeSPI wrapped = isUsingRepeatableRead ? new RepeatableReadNode(in) : new ReadCommittedNode(in);
+ boolean needToCopy = false;
+ if (lockForWriting && !isLocked(context, fqn))
+ {
+ lockManager.lockAndRecord(fqn, WRITE, context);
+ needToCopy = true;
+ }
+ ReadCommittedNode wrapped = nodeFactory.createMvccNode(in);
context.putLookedUpNode(fqn, wrapped);
+ if (needToCopy) wrapped.copyNodeForUpdate(dataContainer, allowWriteSkew);
return wrapped;
}
@@ -370,20 +472,26 @@
if (createIfAbsent)
{
Fqn parentFqn = fqn.getParent();
- NodeSPI parent = getWrappedNode(context, parentFqn, false, createIfAbsent);
+ NodeSPI parent = getWrappedNode(context, parentFqn, false, createIfAbsent, false);
// do we need to lock the parent to create children?
if (lockParentForChildInsertRemove || parent.isLockForChildInsertRemove())
{
// get a lock on the parent.
- if (!isLocked(context, parentFqn)) lockManager.lockAndRecord(parentFqn, WRITE, context);
+ if (!isLocked(context, parentFqn))
+ {
+ lockManager.lockAndRecord(parentFqn, WRITE, context);
+ ReadCommittedNode parentRCN = (ReadCommittedNode) context.lookUpNode(parentFqn);
+ parentRCN.copyNodeForUpdate(dataContainer, allowWriteSkew);
+ }
}
// now to lock and create the node.
if (!isLocked(context, fqn)) lockManager.lockAndRecord(fqn, WRITE, context);
NodeSPI temp = parent.getOrCreateChild(fqn.getLastElement(), context.getGlobalTransaction());
in = (InternalNode) ((NodeInvocationDelegate) temp).getDelegationTarget();
- NodeSPI wrapped = isUsingRepeatableRead ? new RepeatableReadNode(in) : new ReadCommittedNode(in);
+ ReadCommittedNode wrapped = nodeFactory.createMvccNode(in);
context.putLookedUpNode(fqn, wrapped);
+ wrapped.copyNodeForUpdate(dataContainer, allowWriteSkew);
return wrapped;
}
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/ReadCommittedNode.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -47,17 +47,16 @@
// TODO: Deal with removes and moves
// TODO: Deal with creating - what if children is null?
+ log.error("Backup is of type " + backup.getClass().getSimpleName());
+ log.error("Node is of type " + node.getClass().getSimpleName());
((NodeReference) backup).setDelegate(((NodeReference) node).getDelegate());
node = backup;
}
public void rollbackUpdate()
{
- if (changed)
- {
- node = backup;
- backup = null;
- changed = false;
- }
+ node = backup;
+ backup = null;
+ changed = false;
}
}
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/RepeatableReadNode.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -1,10 +1,10 @@
package org.jboss.cache.mvcc;
-import org.jboss.cache.CacheException;
import org.jboss.cache.DataContainer;
import org.jboss.cache.NodeFactory;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.optimistic.DataVersion;
+import org.jboss.cache.optimistic.DataVersioningException;
import org.jboss.cache.optimistic.DefaultDataVersion;
/**
@@ -23,21 +23,37 @@
@Override
public void copyNodeForUpdate(DataContainer container, boolean ignoreWriteSkew)
{
+ // mark node as changed.
changed = true;
- backup = node;
- // write skew check
- DataVersion underlyingNodeVersion = container.peek(getFqn()).getVersion();
- if (ignoreWriteSkew || backup.getVersion().equals(underlyingNodeVersion))
+
+ // check for write skew.
+ NodeSPI underlyingNode = container.peek(getFqn(), false, true); // even check for invalid nodes. we should check tombstones too.
+ DataVersion underlyingNodeVersion = underlyingNode == null ? null : underlyingNode.getVersion();
+ if (!ignoreWriteSkew && underlyingNode != null && !node.getVersion().equals(underlyingNodeVersion))
{
- node = backup.copy();
- // TODO: Make sure this works with custom versions as well!
- DataVersion newVersion = ((DefaultDataVersion) node.getVersion()).increment();
- node.setVersion(newVersion);
+ throw new DataVersioningException("Detected write skew. Attempting to overwrite version " + node.getVersion() + " but current version has progressed to " + underlyingNodeVersion);
}
- else
- {
- throw new CacheException("Detected write skew. Attempting to overwrite version " + backup.getVersion() + " but current version has progressed to " + underlyingNodeVersion);
- }
+
+ // make a backup copy
+ backup = node;
+ node = backup.copy();
+
+ // update version on copy
+ // TODO: Make sure this works with custom versions as well!
+ DataVersion newVersion = ((DefaultDataVersion) node.getVersion()).increment();
+ node.setVersion(newVersion);
+
+ // update parent nodes references - May not be necessary, we could just make sure we don't overwrite child maps when
+ // updateNode() runs.
+
+// if (!getFqn().isRoot())
+// {
+// RepeatableReadNode parent = (RepeatableReadNode) ctx.lookUpNode(getFqn().getParent());
+// if (parent.changed)
+// {
+// parent.addChildDirect();
+// }
+// }
}
@Override
@@ -51,7 +67,15 @@
else
{
NodeSPI parent = dataContainer.peek(getFqn().getParent());
- parent.addChildDirect(nf.createNodeInvocationDelegate(node));
+ if (parent != null)
+ {
+ NodeSPI oldChild = parent.getChildDirect(getFqn().getLastElement());
+ if (oldChild != null)
+ {
+ node.setChildrenMapDirect(oldChild.getChildrenMapDirect());
+ }
+ parent.addChildDirect(nf.createNodeInvocationDelegate(node));
+ }
}
}
}
Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/LockTestBase.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -31,14 +31,14 @@
@Test(groups = {"functional", "mvcc"})
public abstract class LockTestBase
{
- Cache<String, String> cache;
- TransactionManager tm;
- Fqn A = Fqn.fromString("/a");
- Fqn AB = Fqn.fromString("/a/b");
- Fqn ABC = Fqn.fromString("/a/b/c");
- Fqn ABCD = Fqn.fromString("/a/b/c/d");
- LockManager lockManager;
- InvocationContextContainer icc;
+ protected Cache<String, String> cache;
+ protected TransactionManager tm;
+ protected Fqn A = Fqn.fromString("/a");
+ protected Fqn AB = Fqn.fromString("/a/b");
+ protected Fqn ABC = Fqn.fromString("/a/b/c");
+ protected Fqn ABCD = Fqn.fromString("/a/b/c/d");
+ protected LockManager lockManager;
+ protected InvocationContextContainer icc;
protected boolean lockParentForInsertRemove = false;
protected boolean repeatableRead = true;
protected boolean allowWriteSkew = false;
@@ -63,20 +63,20 @@
TestingUtil.killCaches(cache);
}
- private void assertLocked(Fqn fqn)
+ protected void assertLocked(Fqn fqn)
{
assert lockManager.isLocked(fqn) : fqn + " not locked!";
assert icc.get().getLocks().contains(fqn) : "Lock not recorded for " + fqn;
}
- private void assertNotLocked(Fqn fqn)
+ protected void assertNotLocked(Fqn fqn)
{
// can't rely on the negative test since other nodes may share the same lock with lock striping.
// assert !lockManager.isLocked(fqn) : fqn + " is locked!";
assert !icc.get().getLocks().contains(fqn) : fqn + " lock recorded!";
}
- private void assertNoLocks()
+ protected void assertNoLocks()
{
LockContainer lc = (LockContainer) TestingUtil.extractField(lockManager, "lockContainer");
assert lc.getNumLocksHeld() == 0 : "Stale locks exist!" + lockManager.printLockInfo();
@@ -347,7 +347,9 @@
assertNoLocks();
tm.begin();
+ assert cache.getNode(A) != null;
assert !(cache.getNode(A).getChildrenNames().isEmpty());
+ assert cache.getNode(A).getChildrenNames().contains(AB.getLastElement());
assertNoLocks();
tm.commit();
assertNoLocks();
@@ -453,7 +455,7 @@
tm.rollback();
tm.resume(reader);
- assert "v".equals(cache.get(AB, "k"));
+ assert "v".equals(cache.get(AB, "k")) : "Expecting 'v' but was " + cache.get(AB, "k");
tm.commit();
// even after commit
@@ -461,6 +463,30 @@
assertNoLocks();
}
+ public void testRollbacksOnNullNode() throws Exception
+ {
+ tm.begin();
+ assert null == cache.get(AB, "k");
+ assert null == cache.getNode(AB);
+ Transaction reader = tm.suspend();
+
+ tm.begin();
+ cache.put(AB, "k", "v");
+ assert null != cache.getNode(AB);
+ assert "v".equals(cache.get(AB, "k"));
+ tm.rollback();
+
+ tm.resume(reader);
+ assert null == cache.get(AB, "k") : "Expecting null but was " + cache.get(AB, "k");
+ assert null == cache.getNode(AB);
+ tm.commit();
+
+ // even after commit
+ assert null == cache.get(AB, "k");
+ assert null == cache.getNode(AB);
+ assertNoLocks();
+ }
+
public void testWriteSkew() throws Exception
{
if (repeatableRead)
Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewLockTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewLockTest.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewLockTest.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -1,14 +1,12 @@
package org.jboss.cache.api.mvcc.repeatable_read;
-import org.jboss.cache.api.mvcc.LockTestBase;
import org.testng.annotations.Test;
@Test(groups = {"functional", "mvcc"})
-public class RepeatableReadNoWriteSkewLockTest extends LockTestBase
+public class RepeatableReadNoWriteSkewLockTest extends RepeatableReadTestBase
{
public RepeatableReadNoWriteSkewLockTest()
{
- repeatableRead = true;
allowWriteSkew = false;
lockParentForInsertRemove = false;
}
Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewWithParentLockTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewWithParentLockTest.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadNoWriteSkewWithParentLockTest.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -1,14 +1,12 @@
package org.jboss.cache.api.mvcc.repeatable_read;
-import org.jboss.cache.api.mvcc.LockTestBase;
import org.testng.annotations.Test;
@Test(groups = {"functional", "mvcc"})
-public class RepeatableReadNoWriteSkewWithParentLockTest extends LockTestBase
+public class RepeatableReadNoWriteSkewWithParentLockTest extends RepeatableReadTestBase
{
public RepeatableReadNoWriteSkewWithParentLockTest()
{
- repeatableRead = true;
allowWriteSkew = false;
lockParentForInsertRemove = true;
}
Added: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadTestBase.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadTestBase.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -0,0 +1,88 @@
+package org.jboss.cache.api.mvcc.repeatable_read;
+
+import org.jboss.cache.api.mvcc.LockTestBase;
+
+import javax.transaction.Transaction;
+
+public abstract class RepeatableReadTestBase extends LockTestBase
+{
+ protected RepeatableReadTestBase()
+ {
+ repeatableRead = true;
+ }
+
+ public void testRepeatableReadWithRemove() throws Exception
+ {
+ cache.put(AB, "k", "v");
+
+ tm.begin();
+ assert cache.getNode(AB) != null;
+ Transaction reader = tm.suspend();
+
+ tm.begin();
+ assert cache.removeNode(AB);
+ assert cache.getNode(AB) == null;
+ tm.commit();
+
+ assert cache.getNode(AB) == null;
+
+ tm.resume(reader);
+ assert cache.getNode(AB) != null;
+ assert "v".equals(cache.get(AB, "k"));
+ tm.commit();
+
+ assert cache.getNode(AB) == null;
+ assertNoLocks();
+ }
+
+ public void testRepeatableReadWithEvict() throws Exception
+ {
+ cache.put(AB, "k", "v");
+
+ tm.begin();
+ assert cache.getNode(AB) != null;
+ Transaction reader = tm.suspend();
+
+ tm.begin();
+ cache.evict(AB);
+ assert cache.getNode(AB) == null;
+ tm.commit();
+
+ assert cache.getNode(AB) == null;
+
+ tm.resume(reader);
+ assert cache.getNode(AB) != null;
+ assert "v".equals(cache.get(AB, "k"));
+ tm.commit();
+
+ assert cache.getNode(AB) == null;
+ assertNoLocks();
+ }
+
+ public void testRepeatableReadWithNull() throws Exception
+ {
+ assert cache.getNode(AB) == null;
+
+ tm.begin();
+ assert cache.getNode(AB) == null;
+ Transaction reader = tm.suspend();
+
+ tm.begin();
+ cache.put(AB, "k", "v");
+ assert cache.getNode(AB) != null;
+ assert "v".equals(cache.get(AB, "k"));
+ tm.commit();
+
+ assert cache.getNode(AB) != null;
+ assert "v".equals(cache.get(AB, "k"));
+
+ tm.resume(reader);
+ assert cache.getNode(AB) == null;
+ assert cache.get(AB, "k") == null;
+ tm.commit();
+
+ assert cache.getNode(AB) != null;
+ assert "v".equals(cache.get(AB, "k"));
+ assertNoLocks();
+ }
+}
Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewLockTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewLockTest.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewLockTest.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -1,14 +1,12 @@
package org.jboss.cache.api.mvcc.repeatable_read;
-import org.jboss.cache.api.mvcc.LockTestBase;
import org.testng.annotations.Test;
@Test(groups = {"functional", "mvcc"})
-public class RepeatableReadWriteSkewLockTest extends LockTestBase
+public class RepeatableReadWriteSkewLockTest extends RepeatableReadTestBase
{
public RepeatableReadWriteSkewLockTest()
{
- repeatableRead = true;
allowWriteSkew = true;
lockParentForInsertRemove = false;
}
Modified: core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewWithParentLockTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewWithParentLockTest.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/RepeatableReadWriteSkewWithParentLockTest.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -1,14 +1,12 @@
package org.jboss.cache.api.mvcc.repeatable_read;
-import org.jboss.cache.api.mvcc.LockTestBase;
import org.testng.annotations.Test;
@Test(groups = {"functional", "mvcc"})
-public class RepeatableReadWriteSkewWithParentLockTest extends LockTestBase
+public class RepeatableReadWriteSkewWithParentLockTest extends RepeatableReadTestBase
{
public RepeatableReadWriteSkewWithParentLockTest()
{
- repeatableRead = true;
allowWriteSkew = true;
lockParentForInsertRemove = true;
}
Modified: core/trunk/src/test/java/org/jboss/cache/commands/write/EvictCommandTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/commands/write/EvictCommandTest.java 2008-06-30 16:49:02 UTC (rev 6128)
+++ core/trunk/src/test/java/org/jboss/cache/commands/write/EvictCommandTest.java 2008-06-30 19:07:05 UTC (rev 6129)
@@ -33,7 +33,7 @@
notifier = control.createMock(Notifier.class);
container = control.createMock(DataContainer.class);
command = new EvictCommand(testFqn);
- command.initialize(notifier, container);
+ command.initialize(notifier, container, false);
nodes = new MockNodesFixture();
}
16 years, 2 months
JBoss Cache SVN: r6128 - in searchable/trunk/src: test/java/org/jboss/cache/search/blackbox and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: navssurtani
Date: 2008-06-30 12:49:02 -0400 (Mon, 30 Jun 2008)
New Revision: 6128
Removed:
searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/ClusteredPOJOCacheTest.java
Modified:
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheCfgImpl.java
searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalPOJOCacheTest.java
Log:
Deleted ClusteredPOJOCache test
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheCfgImpl.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheCfgImpl.java 2008-06-30 16:44:47 UTC (rev 6127)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheCfgImpl.java 2008-06-30 16:49:02 UTC (rev 6128)
@@ -32,9 +32,9 @@
// populate your Map
// you bog
- for (int i = 0; i <= classArray.length; i++)
+ for (Class c: classArray)
{
- String classname = classArray[i].getName();
+ String classname = c.getName();
RootClass rc = new RootClass();
rc.setClassName(classname);
classes.put(classname, rc);
Deleted: searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/ClusteredPOJOCacheTest.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/ClusteredPOJOCacheTest.java 2008-06-30 16:44:47 UTC (rev 6127)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/ClusteredPOJOCacheTest.java 2008-06-30 16:49:02 UTC (rev 6128)
@@ -1,8 +0,0 @@
-package org.jboss.cache.search.blackbox;
-
-/**
- * @author Navin Surtani - navin(a)surtani.org
- */
-public class ClusteredPOJOCacheTest
-{
-}
Modified: searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalPOJOCacheTest.java
===================================================================
--- searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalPOJOCacheTest.java 2008-06-30 16:44:47 UTC (rev 6127)
+++ searchable/trunk/src/test/java/org/jboss/cache/search/blackbox/LocalPOJOCacheTest.java 2008-06-30 16:49:02 UTC (rev 6128)
@@ -178,4 +178,4 @@
}
-}
+
16 years, 2 months