Build failed in Hudson: jboss-cache-searchable-trunk-jdk1.5 » JBoss Cache - Searchable Edition #14
by jboss-qa-internal@redhat.com
See http://hudson.qa.jboss.com/hudson/job/jboss-cache-searchable-trunk-jdk1.5...
Changes:
[navssurtani] Trying to get pojocache compatibility
------------------------------------------
started
Building remotely on soavmg2-linux
$ /qa/tools/opt/jdk1.5.0_15/bin/java -Xmx512m -cp /home/hudson/hudson_workspace/maven-agent.jar:/qa/tools/opt/maven-2.0.9/boot/classworlds-1.1.jar hudson.maven.agent.Main /qa/tools/opt/maven-2.0.9 /qa/services/hudson/hudson_release/WEB-INF/slave.jar /home/hudson/hudson_workspace/maven-interceptor.jar
channel started
[INFO] Scanning for projects...
WAGON_VERSION: 1.0-beta-2
[INFO] ------------------------------------------------------------------------
[INFO] Building JBoss Cache - Searchable Edition
[INFO] task-segment: [clean, site]
[INFO] ------------------------------------------------------------------------
[INFO] snapshot org.codehaus.mojo:emma-maven-plugin:1.0-SNAPSHOT: checking for updates from snapshots.jboss.org
[INFO] snapshot org.codehaus.mojo:emma-maven-plugin:1.0-SNAPSHOT: checking for updates from Main Maven Repo
[INFO] snapshot org.codehaus.mojo:emma-maven-plugin:1.0-SNAPSHOT: checking for updates from snapshots.repository.codehaus.org
[INFO] snapshot org.codehaus.mojo:emma-maven-plugin:1.0-SNAPSHOT: checking for updates from snapshots.jboss.org
[INFO] snapshot org.codehaus.mojo:emma-maven-plugin:1.0-SNAPSHOT: checking for updates from e-xml.sourceforge.net
Downloading: http://repository.jboss.org/maven2/org/codehaus/mojo/mojo-sandbox/4/mojo-...
Downloading: http://repo1.maven.org/maven2//org/codehaus/mojo/mojo-sandbox/4/mojo-sand...
2K downloaded
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from repository.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from Main Maven Repo
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from snapshots.repository.codehaus.org
[INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from central
[INFO] artifact org.apache.maven.plugins:maven-idea-plugin: checking for updates from repository.jboss.org
[INFO] artifact org.apache.maven.plugins:maven-idea-plugin: checking for updates from Main Maven Repo
[INFO] artifact org.apache.maven.plugins:maven-idea-plugin: checking for updates from snapshots.repository.codehaus.org
[INFO] artifact org.apache.maven.plugins:maven-idea-plugin: checking for updates from central
[HUDSON] Archiving /home/hudson/hudson_workspace/workspace/jboss-cache-searchable-trunk-jdk1.5/./pom.xml
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] The plugin 'org.apache.maven.plugins:maven-idea-plugin' does not exist or no valid version could be found
[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 35 seconds
[INFO] Finished at: Mon Sep 29 12:04:00 EDT 2008
[INFO] Final Memory: 9M/16M
[INFO] ------------------------------------------------------------------------
Waiting for Hudson to finish collecting data
16 years, 1 month
JBoss Cache SVN: r7187 - core/trunk/src/test/java/org/jboss/cache/integration/websession/util.
by jbosscache-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2008-11-24 02:17:06 -0500 (Mon, 24 Nov 2008)
New Revision: 7187
Modified:
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java
Log:
Rearrange a bit
Modified: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java 2008-11-24 07:01:36 UTC (rev 7186)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java 2008-11-24 07:17:06 UTC (rev 7187)
@@ -374,63 +374,6 @@
return appMetadata.granularity;
}
- private Fqn<String> getSessionFqn(String id)
- {
- return Fqn.fromRelativeElements(baseFqn, id);
- }
-
- private Session createEmptySession()
- {
- Session session = null;
- switch (appMetadata.granularity)
- {
- case SESSION:
- case ATTRIBUTE:
- session = new Session(this);
- break;
- case FIELD:
- throw new IllegalStateException("implement");
- }
- return session;
- }
-
- /**
- * JBC read of a session.
- */
- private Session loadSession(String id)
- {
- Session session = null;
-
- boolean startTx = !isBatchStarted();
- if (startTx)
- startBatch();
- Map<Object, Object> data = null;
- try
- {
- if (buddyReplication)
- {
- cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
- }
- data = cache.getData(getSessionFqn(id));
- }
- finally
- {
- if (startTx)
- endBatch();
- }
-
- if (data != null)
- {
- session = createEmptySession();
- AtomicInteger version = (AtomicInteger) data.get(VERSION);
- AtomicLong timestamp = (AtomicLong) data.get(TIMESTAMP);
- SessionMetadata metadata = (SessionMetadata) data.get(METADATA);
- Map<String, Object> attributes = loadSessionAttributes(id, data);
- session.update(version, timestamp, metadata, attributes);
- }
- return session;
- }
-
@SuppressWarnings("unchecked")
protected Map<String, Object> loadSessionAttributes(String id, Map<Object, Object> sessionNodeData)
{
@@ -506,6 +449,65 @@
}
}
+ // ----------------------------------------------------------------- Private
+
+ private Fqn<String> getSessionFqn(String id)
+ {
+ return Fqn.fromRelativeElements(baseFqn, id);
+ }
+
+ private Session createEmptySession()
+ {
+ Session session = null;
+ switch (appMetadata.granularity)
+ {
+ case SESSION:
+ case ATTRIBUTE:
+ session = new Session(this);
+ break;
+ case FIELD:
+ throw new IllegalStateException("implement");
+ }
+ return session;
+ }
+
+ /**
+ * JBC read of a session.
+ */
+ private Session loadSession(String id)
+ {
+ Session session = null;
+
+ boolean startTx = !isBatchStarted();
+ if (startTx)
+ startBatch();
+ Map<Object, Object> data = null;
+ try
+ {
+ if (buddyReplication)
+ {
+ cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
+ }
+ data = cache.getData(getSessionFqn(id));
+ }
+ finally
+ {
+ if (startTx)
+ endBatch();
+ }
+
+ if (data != null)
+ {
+ session = createEmptySession();
+ AtomicInteger version = (AtomicInteger) data.get(VERSION);
+ AtomicLong timestamp = (AtomicLong) data.get(TIMESTAMP);
+ SessionMetadata metadata = (SessionMetadata) data.get(METADATA);
+ Map<String, Object> attributes = loadSessionAttributes(id, data);
+ session.update(version, timestamp, metadata, attributes);
+ }
+ return session;
+ }
+
private boolean sessionChangedInDistributedCache(String realId, String owner, int version)
{
Session session = sessions.get(realId);
16 years, 1 month
JBoss Cache SVN: r7186 - in core/trunk/src/test: java/org/jboss/cache/integration/websession and 3 other directories.
by jbosscache-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2008-11-24 02:01:36 -0500 (Mon, 24 Nov 2008)
New Revision: 7186
Added:
core/trunk/src/test/java/org/jboss/cache/integration/CacheManagerSupport.java
core/trunk/src/test/java/org/jboss/cache/integration/JGroupsUtil.java
core/trunk/src/test/java/org/jboss/cache/integration/MockChannelFactory.java
core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryCacheManager.java
core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryConfigurationRegistry.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/
core/trunk/src/test/java/org/jboss/cache/integration/websession/BuddyReplicationFailoverTest.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/AbstractServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/BuddyReplicationAssertions.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/DirtyMetadataServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/FqnUtil.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/GetAttributesServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/InvalidationServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/MultipleActionServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/RemoveAttributesServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Request.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Servlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Session.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManagerSupport.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionMetadata.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SetAttributesServlet.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebAppMetadata.java
core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebSessionTestBase.java
core/trunk/src/test/resources/configs/integration/
core/trunk/src/test/resources/configs/integration/hibernate-cache-configs.xml
core/trunk/src/test/resources/configs/integration/jgroups-channelfactory-stacks.xml
core/trunk/src/test/resources/configs/integration/sfsb-cache-configs.xml
core/trunk/src/test/resources/configs/integration/web-session-cache-configs.xml
Log:
[JBCACHE-1445] Add test showing problem with cleanup after data gravitation
Added: core/trunk/src/test/java/org/jboss/cache/integration/CacheManagerSupport.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/CacheManagerSupport.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/CacheManagerSupport.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.cache.CacheManager;
+
+/**
+ * @author Brian Stansberry
+ */
+public class CacheManagerSupport
+{
+ /**
+ * For each thread holds list of cache managers created using this factory.
+ */
+ private static final ThreadLocal<List<UnitTestCacheFactoryCacheManager>> threadCacheManagers =
+ new ThreadLocal<List<UnitTestCacheFactoryCacheManager>>()
+ {
+ @Override
+ protected List<UnitTestCacheFactoryCacheManager> initialValue()
+ {
+ return new ArrayList<UnitTestCacheFactoryCacheManager>();
+ }
+ };
+
+ public static List<CacheManager> createCacheManagers(int count, String cacheConfigFileName, String stacksXmlFileName)
+ {
+ List<UnitTestCacheFactoryCacheManager> existing = threadCacheManagers.get();
+ List<CacheManager> result = new ArrayList<CacheManager>(count);
+ int added = 0;
+ for (UnitTestCacheFactoryCacheManager cm : existing)
+ {
+ if (cacheConfigFileName.equals(cm.getCacheConfigFileName()) && stacksXmlFileName.equals(cm.getStacksXMLFileName()))
+ {
+ result.add(cm);
+ added++;
+ }
+ }
+
+ for (; added < count; added++)
+ {
+ UnitTestCacheFactoryCacheManager cm = new UnitTestCacheFactoryCacheManager(cacheConfigFileName, stacksXmlFileName);
+ try
+ {
+ cm.start();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ result.add(cm);
+ existing.add(cm);
+ }
+
+ return result;
+ }
+
+ public static void tearDown()
+ {
+ List<UnitTestCacheFactoryCacheManager> existing = threadCacheManagers.get();
+ for (UnitTestCacheFactoryCacheManager cm : existing)
+ {
+ cm.stop();
+ }
+ threadCacheManagers.remove();
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/JGroupsUtil.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/JGroupsUtil.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/JGroupsUtil.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,153 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.jboss.cache.config.ConfigurationException;
+import org.jboss.cache.util.FileLookup;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * JGroups-related utilities.
+ *
+ * @author Brian Stansberry
+ */
+public class JGroupsUtil
+{
+ private final static String PROTOCOL_STACKS = "protocol_stacks";
+ private final static String STACK = "stack";
+ private static final String NAME = "name";
+ private static final String CONFIG = "config";
+
+ public static Map<String, Element> getStackConfigs(String stacksXmlResource) throws Exception
+ {
+ FileLookup fileLookup = new FileLookup();
+ InputStream is = fileLookup.lookupFile(stacksXmlResource);
+ if (is == null)
+ {
+ throw new ConfigurationException("Unable to find config file " + stacksXmlResource + " either in classpath or on the filesystem!");
+ }
+
+ return getStackConfigs(is);
+ }
+
+ /**
+ * Parses a set if "config" elements out of a JGroups stacks.xml file.
+ *
+ * @param input
+ * @return
+ * @throws Exception
+ */
+ public static Map<String, Element> getStackConfigs(InputStream input) throws Exception
+ {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setValidating(false); //for now
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document document = builder.parse(input);
+
+ // The root element of the document should be the "config" element,
+ // but the parser(Element) method checks this so a check is not
+ // needed here.
+ Element configElement = document.getDocumentElement();
+ return getStackConfigs(configElement);
+ }
+
+ private static Map<String, Element> getStackConfigs(Element root) throws Exception
+ {
+ Map<String, Element> result = new HashMap<String, Element>();
+
+ String root_name = root.getNodeName();
+ if (!PROTOCOL_STACKS.equals(root_name.trim().toLowerCase()))
+ {
+ String error = "XML protocol stack configuration does not start with a '<config>' element; "
+ + "maybe the XML configuration needs to be converted to the new format ?\n"
+ + "use 'java org.jgroups.conf.XmlConfigurator <old XML file> -new_format' to do so";
+ throw new IOException("invalid XML configuration: " + error);
+ }
+
+ NodeList tmp_stacks = root.getChildNodes();
+ for (int i = 0; i < tmp_stacks.getLength(); i++)
+ {
+ Node node = tmp_stacks.item(i);
+ if (node.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ Element stack = (Element) node;
+ String tmp = stack.getNodeName();
+ if (!STACK.equals(tmp.trim().toLowerCase()))
+ {
+ throw new IOException("invalid configuration: didn't find a \"" + STACK + "\" element under \""
+ + PROTOCOL_STACKS + "\"");
+ }
+
+ NamedNodeMap attrs = stack.getAttributes();
+ Node name = attrs.getNamedItem(NAME);
+ String st_name = name.getNodeValue();
+
+ NodeList configs = stack.getChildNodes();
+ for (int j = 0; j < configs.getLength(); j++)
+ {
+ Node tmp_config = configs.item(j);
+ if (tmp_config.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+ Element cfg = (Element) tmp_config;
+ tmp = cfg.getNodeName();
+ if (!CONFIG.equals(tmp))
+ throw new IOException("invalid configuration: didn't find a \"" + CONFIG + "\" element under \"" + STACK
+ + "\"");
+
+ if (!result.containsKey(st_name))
+ {
+ result.put(st_name, cfg);
+ }
+ else
+ {
+ throw new IllegalStateException("didn't add config '" + st_name
+ + " because one of the same name already existed");
+ }
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Prevent instantiation.
+ */
+ private JGroupsUtil()
+ {
+ throw new UnsupportedOperationException("just a static util class");
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/MockChannelFactory.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/MockChannelFactory.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/MockChannelFactory.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration;
+
+import java.io.File;
+import java.net.URL;
+
+import org.jgroups.Channel;
+import org.jgroups.ChannelException;
+import org.jgroups.ChannelFactory;
+import org.w3c.dom.Element;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class MockChannelFactory implements ChannelFactory
+{
+ public static final MockChannelFactory INSTANCE = new MockChannelFactory();
+
+ private MockChannelFactory() {}
+
+ public Channel createChannel() throws ChannelException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Channel createChannel(Object props) throws ChannelException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Channel createChannel(String stack_name) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Channel createMultiplexerChannel(String stack_name, String id) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Channel createMultiplexerChannel(String stack_name, String id, boolean register_for_state_transfer,
+ String substate_id) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMultiplexerConfig(Object properties) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMultiplexerConfig(File properties) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMultiplexerConfig(Element properties) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMultiplexerConfig(URL properties) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void setMultiplexerConfig(String properties) throws Exception
+ {
+ throw new UnsupportedOperationException();
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryCacheManager.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryCacheManager.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryCacheManager.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,81 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheManagerImpl;
+import org.jboss.cache.UnitTestCacheFactory;
+import org.jboss.cache.config.Configuration;
+
+/**
+ * CacheManager implementation that integrates with UnitTestCacheFactory.
+ *
+ * @author Brian Stansberry
+ */
+public class UnitTestCacheFactoryCacheManager extends CacheManagerImpl
+{
+ private final String cacheConfigFileName;
+ private final String stacksXMLFileName;
+
+ /**
+ * Create a new UnitTestCacheFactoryCacheManager.
+ *
+ * @param configFileName
+ * @param factory
+ */
+ public UnitTestCacheFactoryCacheManager(String cacheConfigFileName, String stacksXMLFileName)
+ {
+ super(new UnitTestCacheFactoryConfigurationRegistry(cacheConfigFileName, stacksXMLFileName), MockChannelFactory.INSTANCE);
+ this.cacheConfigFileName = cacheConfigFileName;
+ this.stacksXMLFileName = stacksXMLFileName;
+ }
+
+ public String getCacheConfigFileName()
+ {
+ return cacheConfigFileName;
+ }
+
+ public String getStacksXMLFileName()
+ {
+ return stacksXMLFileName;
+ }
+
+ @Override
+ public void start() throws Exception
+ {
+ ((UnitTestCacheFactoryConfigurationRegistry) getConfigurationRegistry()).start();
+ super.start();
+ }
+
+ /**
+ * Overrides superclass to use UnitTestCacheFactory to create the cache.
+ */
+ @Override
+ protected Cache<Object, Object> createCache(Configuration config)
+ {
+ return new UnitTestCacheFactory<Object, Object>().createCache(config, false);
+ }
+
+
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryConfigurationRegistry.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryConfigurationRegistry.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/UnitTestCacheFactoryConfigurationRegistry.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,177 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration;
+
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.ConfigurationRegistry;
+import org.jboss.cache.config.parsing.CacheConfigsXmlParser;
+import org.w3c.dom.Element;
+
+/**
+ * XmlParsingConfigurationRegistry variant that replaces any MuxStackName in
+ * configurations with a corresponding Element parsed out of the provided
+ * JGroups stacks.xml file. UnitTestCacheFactory can then mangle the element.
+ *
+ * @author <a href="brian.stansberry(a)jboss.com">Brian Stansberry</a>
+ * @version $Revision: 7168 $
+ */
+public class UnitTestCacheFactoryConfigurationRegistry implements ConfigurationRegistry
+{
+ public static final String DEFAULT_STACKS_XML_RESOURCE = "configs/integration/jgroups-channelfactory-stacks.xml";
+
+ private final CacheConfigsXmlParser parser;
+ private final String configResource;
+ private final Map<String, Element> stacks;
+ private final Map<String, Configuration> configs = new Hashtable<String, Configuration>();
+ private boolean started;
+
+ public UnitTestCacheFactoryConfigurationRegistry(String cacheConfigResource)
+ {
+ this(cacheConfigResource, DEFAULT_STACKS_XML_RESOURCE);
+ }
+
+ public UnitTestCacheFactoryConfigurationRegistry(String cacheConfigResource, String stacksXmlResource)
+ {
+ parser = new CacheConfigsXmlParser();
+ this.configResource = cacheConfigResource;
+ try
+ {
+ this.stacks = JGroupsUtil.getStackConfigs(stacksXmlResource);
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("problem parsing JGroups stacks", e);
+ }
+ }
+
+ public void start() throws Exception
+ {
+ if (!started)
+ {
+ if (configResource != null)
+ {
+ Map<String, Configuration> parsed = parser.parseConfigs(configResource);
+ for (Map.Entry<String, Configuration> entry : parsed.entrySet())
+ {
+ registerConfiguration(entry.getKey(), entry.getValue());
+ }
+ }
+ started = true;
+ }
+ }
+
+ public void stop()
+ {
+ if (started)
+ {
+ synchronized (configs)
+ {
+ configs.clear();
+ }
+ started = false;
+ }
+ }
+
+ public String getConfigResource()
+ {
+ return configResource;
+ }
+
+ public Set<String> getConfigurationNames()
+ {
+ return new HashSet<String>(configs.keySet());
+ }
+
+ public void registerConfiguration(String configName, Configuration config)
+ throws CloneNotSupportedException
+ {
+ synchronized (configs)
+ {
+ if (configs.containsKey(configName))
+ throw new IllegalStateException(configName + " already registered");
+ Configuration clone = config.clone();
+ fixJGroupsConfig(clone);
+ configs.put(configName, clone);
+ }
+ }
+
+ public void unregisterConfiguration(String configName)
+ {
+ synchronized (configs)
+ {
+ if (configs.remove(configName) == null)
+ throw new IllegalStateException(configName + " not registered");
+ }
+ }
+
+ public Configuration getConfiguration(String configName)
+ {
+ Configuration config;
+ synchronized (configs)
+ {
+ config = configs.get(configName);
+ }
+
+ if (config == null)
+ throw new IllegalArgumentException("unknown config " + configName);
+
+ // Don't hand out a ref to our master copy
+ try
+ {
+ return config.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ // This should not happen, as we already cloned the config
+ throw new RuntimeException("Could not clone configuration " + configName, e);
+ }
+ }
+
+ /** Replace a stack name with a stack element that UnitTestCacheFactory can mangle */
+ private void fixJGroupsConfig(Configuration clone)
+ {
+ String stackName = clone.getMultiplexerStack();
+ if (stackName != null)
+ {
+ clone.setMultiplexerStack(null);
+ Element e = stacks.get(stackName);
+ if (e == null)
+ {
+ throw new IllegalStateException("unknown stack " + stackName);
+ }
+
+ clone.setClusterConfig(e);
+ }
+
+ }
+
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/BuddyReplicationFailoverTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/BuddyReplicationFailoverTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/BuddyReplicationFailoverTest.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,159 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession;
+
+import java.util.Collections;
+
+import org.jboss.cache.commands.write.PutDataMapCommand;
+import org.jboss.cache.commands.write.RemoveNodeCommand;
+import org.jboss.cache.integration.websession.util.BuddyReplicationAssertions;
+import org.jboss.cache.integration.websession.util.GetAttributesServlet;
+import org.jboss.cache.integration.websession.util.InvalidationServlet;
+import org.jboss.cache.integration.websession.util.MultipleActionServlet;
+import org.jboss.cache.integration.websession.util.Request;
+import org.jboss.cache.integration.websession.util.SessionManager;
+import org.jboss.cache.integration.websession.util.SetAttributesServlet;
+import org.jboss.cache.integration.websession.util.WebSessionTestBase;
+import org.jboss.cache.util.internals.replicationlisteners.ReplicationListener;
+import org.testng.annotations.Test;
+
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+@Test(groups = "integration", sequential = true, testName = "integration.websession.BuddyReplicationFailoverTest")
+public class BuddyReplicationFailoverTest extends WebSessionTestBase
+{
+ public static final String KEY = "key";
+
+ @Override
+ protected String getCacheConfigName()
+ {
+ return "br-standard-session-cache";
+ }
+
+ @Override
+ protected int getNumCacheManagers()
+ {
+ return 4;
+ }
+
+ @Override
+ protected boolean getCreateManagersInSetup()
+ {
+ return true;
+ }
+
+ public void testFailoverAndFailBack()
+ {
+ int attr = 0;
+
+ SessionManager mgr0 = getSessionManagers().get(0);
+ SessionManager mgr1 = getSessionManagers().get(1);
+ SessionManager mgr2 = getSessionManagers().get(2);
+ SessionManager mgr3 = getSessionManagers().get(3);
+
+ String contextHostName = mgr0.getContextHostName();
+
+ // Create the session
+ SetAttributesServlet sas = new SetAttributesServlet(Collections.singletonMap(KEY, getAttributeValue(attr++)));
+ ReplicationListener replListener1 = ReplicationListener.getReplicationListener(mgr1.getCache());
+ replListener1.expectWithTx(PutDataMapCommand.class);
+
+ Request req = new Request(mgr0, null, sas);
+ req.execute();
+ replListener1.waitForReplicationToOccur();
+
+ String sessionId = sas.getSessionId();
+ assert sessionId != null : "session id is null";
+ // validate cache contents
+ BuddyReplicationAssertions.assertBuddyBackup(contextHostName, sessionId, mgr0.getCache(), mgr1.getCache());
+
+ // Modify the session
+ sas = new SetAttributesServlet(Collections.singletonMap(KEY, getAttributeValue(attr++)));
+ replListener1.expectWithTx(PutDataMapCommand.class);
+
+ req = new Request(mgr0, sessionId, sas);
+ req.execute();
+ replListener1.waitForReplicationToOccur();
+
+ // Fail over; request reads the session and then modifies the session
+ GetAttributesServlet gas = new GetAttributesServlet(Collections.singleton(KEY));
+ sas = new SetAttributesServlet(Collections.singletonMap(KEY, getAttributeValue(attr++)));
+ MultipleActionServlet mas = new MultipleActionServlet(gas, sas);
+ ReplicationListener replListener0 = ReplicationListener.getReplicationListener(mgr0.getCache());
+ replListener0.expectWithTx(PutDataMapCommand.class);
+
+ req = new Request(mgr3, sessionId, mas);
+ req.execute();
+ replListener0.waitForReplicationToOccur();
+
+ assert sessionId.equals(mas.getSessionId()) : "wrong session id; expected " + sessionId + " got " + mas.getSessionId();
+ Integer integer = (Integer) gas.getReadAttributes().get(KEY);
+ assert integer != null : "null attribute value";
+ assert integer.intValue() == (attr - 2) : "wrong val " + integer + " expected " + (attr -2);
+
+ BuddyReplicationAssertions.assertBuddyBackup(contextHostName, sessionId, mgr3.getCache(), mgr0.getCache());
+ BuddyReplicationAssertions.assertUnrelated(contextHostName, sessionId, mgr1.getCache());
+
+ // Modify the session again
+ sas = new SetAttributesServlet(Collections.singletonMap(KEY, getAttributeValue(attr++)));
+ replListener0.expectWithTx(PutDataMapCommand.class);
+
+ req = new Request(mgr3, sessionId, sas);
+ req.execute();
+ replListener0.waitForReplicationToOccur();
+
+ // Fail back; request reads the session and then modifies the session
+ gas = new GetAttributesServlet(Collections.singleton(KEY));
+ sas = new SetAttributesServlet(Collections.singletonMap(KEY, getAttributeValue(attr++)));
+ mas = new MultipleActionServlet(gas, sas);
+ replListener1.expectWithTx(PutDataMapCommand.class);
+
+ req = new Request(mgr0, sessionId, mas);
+ req.execute();
+ replListener1.waitForReplicationToOccur();
+
+ assert sessionId.equals(mas.getSessionId()) : "wrong session id; expected " + sessionId + " got " + mas.getSessionId();
+ integer = (Integer) gas.getReadAttributes().get(KEY);
+ assert integer != null : "null attribute value";
+ assert integer.intValue() == attr - 2 : "wrong val " + integer + " expected " + (attr -2);
+
+ BuddyReplicationAssertions.assertBuddyBackup(contextHostName, sessionId, mgr0.getCache(), mgr1.getCache());
+ BuddyReplicationAssertions.assertUnrelated(contextHostName, sessionId, mgr3.getCache());
+
+ // Invalidate the session
+ InvalidationServlet invs = new InvalidationServlet();
+ replListener1.expectWithTx(RemoveNodeCommand.class);
+
+ req = new Request(mgr0, sessionId, invs);
+ req.execute();
+ replListener1.waitForReplicationToOccur();
+
+ BuddyReplicationAssertions.assertUnrelated(contextHostName, sessionId, mgr0.getCache());
+ BuddyReplicationAssertions.assertUnrelated(contextHostName, sessionId, mgr1.getCache());
+ BuddyReplicationAssertions.assertUnrelated(contextHostName, sessionId, mgr2.getCache());
+ BuddyReplicationAssertions.assertUnrelated(contextHostName, sessionId, mgr3.getCache());
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/AbstractServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/AbstractServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/AbstractServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,57 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+/**
+ * Basic Servlet impl. Caches a reference to the session.
+ * @author Brian Stansberry
+ *
+ */
+public abstract class AbstractServlet implements Servlet
+{
+ private Session session;
+
+ protected Session extractSession(Request request)
+ {
+ if (session == null)
+ {
+ session = request.getSession(true);
+ }
+ return session;
+ }
+
+ protected void clearSession()
+ {
+ session = null;
+ }
+
+ public Session getSession()
+ {
+ return session;
+ }
+
+ public String getSessionId()
+ {
+ return session == null ? null : session.getId();
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/BuddyReplicationAssertions.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/BuddyReplicationAssertions.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/BuddyReplicationAssertions.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,89 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.Map;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.cache.buddyreplication.BuddyManager;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class BuddyReplicationAssertions
+{
+ public static void assertBuddyBackup(String contextHostName, String sessionId, Cache<Object, Object> owner, Cache<Object, Object> backup)
+ {
+ Fqn<String> fqn = Fqn.fromElements(FqnUtil.JSESSION, contextHostName, sessionId);
+ Map<Object, Object> owned = owner.getData(fqn);
+ assert owned != null : "owned is null";
+
+ Fqn bFqn = new BuddyFqnTransformer().getBackupFqn(owner.getLocalAddress(), fqn);
+ Map<Object, Object> backed = owner.getData(fqn);
+ assert backed != null : "backed is null";
+
+ assert owned.size() == backed.size() : "sizes differ; owned = " + owned.size() + " backed = " + backed.size();
+
+ for (Map.Entry<Object, Object> entry : owned.entrySet())
+ {
+ Object backVal = backed.get(entry.getKey());
+ assert backVal != null : "null backVal for " + entry.getKey();
+ assert backVal.equals(entry.getValue()) : "differing val for " + entry.getKey() + " " + entry.getValue() + " vs. " + backVal;
+ }
+
+ assertMainTreeClear(contextHostName, sessionId, backup);
+ assertBuddyTreeClear(contextHostName, sessionId, owner);
+ }
+
+ public static void assertUnrelated(String contextHostName, String sessionId, Cache<Object, Object> cache)
+ {
+ assertMainTreeClear(contextHostName, sessionId, cache);
+ assertBuddyTreeClear(contextHostName, sessionId, cache);
+ }
+
+ public static void assertMainTreeClear(String contextHostName, String sessionId, Cache<Object, Object> cache)
+ {
+ Fqn<String> fqn = Fqn.fromElements(FqnUtil.JSESSION, contextHostName, sessionId);
+ assert cache.getNode(fqn) == null : "found node for " + fqn;
+ }
+
+ public static void assertBuddyTreeClear(String contextHostName, String sessionId, Cache<Object, Object> cache)
+ {
+ Fqn<String> fqn = Fqn.fromElements(FqnUtil.JSESSION, contextHostName, sessionId);
+ Node<Object, Object> bbRoot = cache.getNode(BuddyManager.BUDDY_BACKUP_SUBTREE_FQN);
+ if (bbRoot != null)
+ {
+ for(Node<Object, Object> child : bbRoot.getChildren())
+ {
+ Node<Object, Object> bad = child.getChild(fqn);
+ assert bad == null : "found bad node at " + Fqn.fromRelativeFqn(child.getFqn(), fqn);
+ }
+ }
+ }
+
+ private BuddyReplicationAssertions() {}
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/DirtyMetadataServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/DirtyMetadataServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/DirtyMetadataServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+
+/**
+ * A Servlet the marks the session metadata dirty.
+ *
+ * @author Brian Stansberry
+ */
+public class DirtyMetadataServlet extends AbstractServlet
+{
+ public void handleRequest(Request request)
+ {
+ extractSession(request).setMetadataDirty();
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/FqnUtil.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/FqnUtil.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/FqnUtil.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.buddyreplication.BuddyManager;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class FqnUtil
+{
+ public static final String JSESSION = "JSESSION";
+ public static final String ATTRIBUTE = "ATTRIBUTE";
+ private static final int JSESSION_FQN_INDEX = 0;
+ private static final int WEBAPP_FQN_INDEX = 1;
+ private static final int SESSION_ID_FQN_INDEX = 2;
+ private static final int SESSION_FQN_SIZE = SESSION_ID_FQN_INDEX + 1;
+ private static final int BUDDY_BACKUP_ROOT_OWNER_INDEX = BuddyManager.BUDDY_BACKUP_SUBTREE_FQN.size();
+ private static final int BUDDY_BACKUP_ROOT_OWNER_SIZE = BUDDY_BACKUP_ROOT_OWNER_INDEX + 1;
+ // Element within an FQN that is the root of a Pojo attribute map
+ private static final int POJO_ATTRIBUTE_FQN_INDEX = SESSION_ID_FQN_INDEX + 1;
+ // Element within an FQN that is the root of an individual Pojo attribute
+ private static final int POJO_KEY_FQN_INDEX = POJO_ATTRIBUTE_FQN_INDEX + 1;
+ // Element within an FQN that is the root of a session's internal pojo storage area
+ private static final int POJO_INTERNAL_FQN_INDEX = SESSION_ID_FQN_INDEX + 1;
+ // Minimum size of an FQN that is below the root of a session's internal pojo storage area
+ private static final int POJO_INTERNAL_FQN_SIZE = POJO_INTERNAL_FQN_INDEX + 1;
+
+ public static boolean isBuddyFqn(Fqn<String> fqn)
+ {
+ try
+ {
+ return BuddyManager.BUDDY_BACKUP_SUBTREE.equals(fqn.get(0));
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ // Can only happen if fqn is ROOT, and we shouldn't get
+ // notifications for ROOT.
+ // If it does, just means it's not a buddy
+ return false;
+ }
+ }
+
+ public static boolean isFqnSessionRootSized(Fqn<String> fqn, boolean isBuddy)
+ {
+ return fqn.size() == (isBuddy ? BUDDY_BACKUP_ROOT_OWNER_SIZE + SESSION_FQN_SIZE : SESSION_FQN_SIZE);
+ }
+
+ public static String getPojoKeyFromFqn(Fqn<String> fqn, boolean isBuddy)
+ {
+ return (String) fqn.get(isBuddy ? BUDDY_BACKUP_ROOT_OWNER_SIZE + POJO_KEY_FQN_INDEX: POJO_KEY_FQN_INDEX);
+ }
+
+ /**
+ * Check if the fqn is big enough to be in the internal pojo area but
+ * isn't in the regular attribute area.
+ *
+ * Structure in the cache is:
+ *
+ * /JSESSION
+ * ++ /contextPath_hostname
+ * ++++ /sessionid
+ * ++++++ /ATTRIBUTE
+ * ++++++ /_JBossInternal_
+ * ++++++++ etc etc
+ *
+ * If the Fqn size is big enough to be "etc etc" or lower, but the 4th
+ * level is not "ATTRIBUTE", it must be under _JBossInternal_. We discriminate
+ * based on != ATTRIBUTE to avoid having to code to the internal PojoCache
+ * _JBossInternal_ name.
+ *
+ * @param fqn
+ * @return
+ */
+ public static boolean isPossibleInternalPojoFqn(Fqn<String> fqn)
+ {
+ return (fqn.size() > POJO_INTERNAL_FQN_SIZE
+ && ATTRIBUTE.equals(fqn.get(POJO_INTERNAL_FQN_INDEX)) == false);
+ }
+
+ public static String getIdFromFqn(Fqn<String> fqn, boolean isBuddy)
+ {
+ return (String)fqn.get(isBuddy ? BUDDY_BACKUP_ROOT_OWNER_SIZE + SESSION_ID_FQN_INDEX : SESSION_ID_FQN_INDEX);
+ }
+
+ /**
+ * Extracts the owner portion of an buddy subtree Fqn.
+ *
+ * @param fqn An Fqn that is a child of the buddy backup root node.
+ */
+ public static String getBuddyOwner(Fqn<String> fqn)
+ {
+ return (String) fqn.get(BUDDY_BACKUP_ROOT_OWNER_INDEX);
+ }
+
+ public static boolean isFqnForOurWebapp(Fqn<String> fqn, String contextHostPath, boolean isBuddy)
+ {
+ try
+ {
+ if (contextHostPath.equals(fqn.get(isBuddy ? BUDDY_BACKUP_ROOT_OWNER_SIZE + WEBAPP_FQN_INDEX : WEBAPP_FQN_INDEX))
+ && JSESSION.equals(fqn.get(isBuddy ? BUDDY_BACKUP_ROOT_OWNER_SIZE + JSESSION_FQN_INDEX : JSESSION_FQN_INDEX)))
+ return true;
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ // can't be ours; too small; just fall through
+ }
+
+ return false;
+ }
+
+ private FqnUtil() {}
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/GetAttributesServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/GetAttributesServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/GetAttributesServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,58 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A Servlet that reads attributes from the session.
+ *
+ * @author Brian Stansberry
+ */
+public class GetAttributesServlet extends AbstractServlet
+{
+ private final Set<String> toGet;
+ private final Map<String, Object> readAttributes = new HashMap<String, Object>();
+
+ public GetAttributesServlet(Set<String> toGet)
+ {
+ this.toGet = new HashSet<String>(toGet);
+ }
+
+ public void handleRequest(Request request)
+ {
+ Session session = extractSession(request);
+ for (String key : toGet)
+ {
+ readAttributes.put(key, session.getAttribute(key));
+ }
+ }
+ public Map<String, Object> getReadAttributes()
+ {
+ return readAttributes;
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/InvalidationServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/InvalidationServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/InvalidationServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+
+/**
+ * A Servlet that invalidates the session.
+ *
+ * @author Brian Stansberry
+ */
+public class InvalidationServlet extends AbstractServlet
+{
+ public void handleRequest(Request request)
+ {
+ extractSession(request).invalidate();
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/MultipleActionServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/MultipleActionServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/MultipleActionServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A Servlet that call other servlets in order.
+ *
+ * @author Brian Stansberry
+ */
+public class MultipleActionServlet extends AbstractServlet
+{
+ private final List<Servlet> actions;
+
+ public MultipleActionServlet(Servlet... action)
+ {
+ this.actions = Arrays.asList(action);
+ }
+
+ public void handleRequest(Request request)
+ {
+ extractSession(request);
+ for (Servlet action : actions)
+ {
+ action.handleRequest(request);
+ }
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/RemoveAttributesServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/RemoveAttributesServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/RemoveAttributesServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A Servlet that removes attributes from the session.
+ *
+ * @author Brian Stansberry
+ */
+public class RemoveAttributesServlet extends AbstractServlet
+{
+ private final Set<String> toRemove;
+
+ public RemoveAttributesServlet(Set<String> toRemove)
+ {
+ this.toRemove = new HashSet<String>(toRemove);
+ }
+
+ public void handleRequest(Request request)
+ {
+ Session session = extractSession(request);
+ for (String key : toRemove)
+ {
+ session.removeAttribute(key);
+ }
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Request.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Request.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Request.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,91 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+/**
+ * Mocks the JBoss AS clustered webapp request handling.
+ *
+ * @author Brian Stansberry
+ */
+public class Request
+{
+ private final SessionManager manager;
+ private final String sessionId;
+ private final Servlet servlet;
+ private Session session;
+
+ public Request(SessionManager manager, String sessionId, Servlet servlet)
+ {
+ this.manager = manager;
+ this.sessionId = sessionId;
+ this.servlet = servlet;
+ }
+
+ public void execute()
+ {
+ // Gravitate the session outside of the batch
+ getSession(false);
+
+ manager.startBatch();
+ try
+ {
+ servlet.handleRequest(this);
+ }
+ finally
+ {
+ try
+ {
+ if (session != null && session.isValid())
+ session.store();
+ }
+ finally
+ {
+ manager.endBatch();
+ }
+ }
+ }
+
+ /**
+ * Meant for internal use in this class and by a Servlet; test driver
+ * should get a session ref from a Servlet impl.
+ */
+ public Session getSession(boolean create)
+ {
+ if (session == null && sessionId != null)
+ {
+ session = manager.findSession(sessionId);
+ }
+
+ if (session != null && !session.isValid())
+ session = null;
+
+ if (create && session == null)
+ session = manager.createSession();
+
+ if (session != null)
+ session.access();
+
+ return session;
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Servlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Servlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Servlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,34 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+/**
+ * Implementations of this interface will actually do something with
+ * the session.
+ *
+ * @author Brian Stansberry
+ */
+public interface Servlet
+{
+ void handleRequest(Request request);
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Session.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Session.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/Session.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,200 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Mock version of a JBoss AS clustered session.
+ *
+ * @author Brian Stansberry
+ */
+public class Session
+{
+ private volatile SessionMetadata metadata = new SessionMetadata();
+ private final AtomicInteger version = new AtomicInteger();
+ private final AtomicLong timestamp = new AtomicLong(metadata.creationTime);
+ private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
+ private final Set<String> modifiedKeys = new HashSet<String>();
+ private final Set<String> removedKeys = new HashSet<String>();
+ private final SessionManager manager;
+ private boolean outdated;
+ private boolean metadataDirty = true;
+
+ public Session(SessionManager manager)
+ {
+ this.manager = manager;
+ }
+
+ public String getId()
+ {
+ return metadata.id;
+ }
+
+ public long getCreationTime()
+ {
+ return metadata.creationTime;
+ }
+
+ public boolean isValid()
+ {
+ return metadata.valid;
+ }
+
+ public void invalidate()
+ {
+ this.metadata.valid = false;
+ manager.removeSession(getId(), false, true);
+ }
+
+ public Object setAttribute(String key, Object value)
+ {
+ modifiedKeys.add(key);
+ removedKeys.remove(key);
+ return attributes.put(key, value);
+ }
+
+ public Object removeAttribute(String key)
+ {
+ removedKeys.add(key);
+ modifiedKeys.remove(key);
+ return attributes.remove(key);
+ }
+
+ public Object getAttribute(String key)
+ {
+ return attributes.get(key);
+ }
+
+ public AtomicLong getTimestamp()
+ {
+ return timestamp;
+ }
+
+ public void setMetadataDirty()
+ {
+ this.metadataDirty = true;
+ }
+
+ public void access()
+ {
+ this.timestamp.set(System.currentTimeMillis());
+ }
+
+ public void store()
+ {
+ version.incrementAndGet();
+
+ switch (manager.getGranularity())
+ {
+ case SESSION:
+ manager.storeSession(getId(), version, timestamp, getMetadataForReplication(), getAttributesForReplication());
+ break;
+ case ATTRIBUTE:
+ Map<String, Object> modified = new HashMap<String, Object>();
+ for (String key : modifiedKeys)
+ {
+ modified.put(key, attributes.get(key));
+ }
+ manager.storeSession(getId(), version, timestamp, getMetadataForReplication(), modified, removedKeys);
+ break;
+ case FIELD:
+ throw new UnsupportedOperationException("implement me");
+ }
+ this.metadataDirty = false;
+ }
+
+ public SessionManager getManager()
+ {
+ return manager;
+ }
+
+ protected Map<String, Object> getAttributes()
+ {
+ return attributes;
+ }
+
+ protected SessionMetadata getMetadata()
+ {
+ return metadata;
+ }
+
+ protected AtomicInteger getVersion()
+ {
+ return version;
+ }
+
+ protected Map<String, Object> getAttributesForReplication()
+ {
+ return attributes;
+ }
+
+ private SessionMetadata getMetadataForReplication()
+ {
+ return metadataDirty ? metadata : null;
+ }
+
+ protected void replicateAttributeChanges()
+ {
+ // no-op
+ }
+
+ protected boolean isOutdated()
+ {
+ return outdated;
+ }
+
+ protected void setOutdated(boolean outdated)
+ {
+ this.outdated = outdated;
+ }
+
+ protected void update(AtomicInteger version, AtomicLong timestamp, SessionMetadata metadata,
+ Map<String, Object> attributes)
+ {
+ if (version == null)
+ throw new IllegalArgumentException("version is null");
+ if (timestamp == null)
+ throw new IllegalArgumentException("timestamp is null");
+ if (metadata == null)
+ throw new IllegalArgumentException("metadata is null");
+ if (attributes == null)
+ throw new IllegalArgumentException("attributes is null");
+
+ this.version.set(version.get());
+ this.timestamp.set(version.get());
+ this.metadata = metadata;
+
+ this.attributes.clear();
+ this.attributes.putAll(attributes);
+
+ this.outdated = false;
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManager.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,530 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheManager;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.BuddyReplicationConfig;
+import org.jboss.cache.integration.websession.util.WebAppMetadata.Granularity;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
+
+/**
+ * Mock version of a JBoss AS web session manager.
+ *
+ * @author Brian Stansberry
+ */
+@CacheListener
+public class SessionManager
+{
+
+ private static final Integer VERSION = Integer.valueOf(0);
+ private static final Integer TIMESTAMP = Integer.valueOf(1);
+ private static final Integer METADATA = Integer.valueOf(2);
+ private static final Integer ATTRIBUTES = Integer.valueOf(3);
+
+ private final CacheManager cacheManager;
+ private final WebAppMetadata appMetadata;
+ private final String contextHostName;
+ private final Fqn<String> baseFqn;
+ private final Map<String, Session> sessions = new ConcurrentHashMap<String, Session>();
+ private Cache<Object, Object> cache;
+ private TransactionManager tm;
+ private boolean buddyReplication;
+ private boolean started;
+ private final boolean fieldBased;
+ private final boolean attributeBased;
+ private final Log log = LogFactory.getLog(getClass());
+
+ // ------------------------------------------------------------ Constructors
+
+ public SessionManager(CacheManager cacheManager, WebAppMetadata metadata)
+ {
+ this.cacheManager = cacheManager;
+ this.appMetadata = metadata;
+ this.contextHostName = appMetadata.warName + "_localhost";
+ this.baseFqn = Fqn.fromElements(FqnUtil.JSESSION, contextHostName);
+ this.fieldBased = appMetadata.granularity == Granularity.FIELD;
+ this.attributeBased = appMetadata.granularity == Granularity.ATTRIBUTE;
+ }
+
+ // --------------------------------------------------------- Test Driver API
+
+ public boolean isStarted()
+ {
+ return started;
+ }
+
+ public void start()
+ {
+ this.started = true;;
+
+ try
+ {
+ this.cache = cacheManager.getCache(appMetadata.cacheConfigName, false);
+ }
+ catch (RuntimeException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+
+ cache.addCacheListener(this);
+
+ if (cache.getCacheStatus() != CacheStatus.STARTED)
+ {
+ cache.start();
+ }
+ this.tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ if (tm == null)
+ {
+ throw new IllegalStateException("tm is null");
+ }
+ BuddyReplicationConfig brc = cache.getConfiguration().getBuddyReplicationConfig();
+ this.buddyReplication = brc != null && brc.isEnabled();
+ }
+
+ public void stop()
+ {
+ if (started)
+ {
+
+
+ if (cache != null)
+ {
+ cache.removeCacheListener(this);
+
+ // FIXME see if we need more sophisticated cache cleanup
+ cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ cache.removeNode(baseFqn);
+ cacheManager.releaseCache(appMetadata.cacheConfigName);
+ cache = null;
+ }
+ }
+ }
+
+ /**
+ * Allows test driver to mock Tomcat background processes' expiration
+ * of an overage session.
+ *
+ * FIXME deal with buddy backup tree
+ *
+ * @param id the session id
+ */
+ public void expireSession(String id)
+ {
+ Session session = removeSession(id, true, true);
+ if (session != null)
+ session.getMetadata().valid = false;
+ }
+
+ /**
+ * Allows test driver to mock Tomcat background processes' passivation
+ * of a session.
+ *
+ * FIXME deal with buddy backup tree
+ *
+ * @param id the session id
+ */
+ public void passivate(String id)
+ {
+ if (!appMetadata.passivation)
+ throw new IllegalStateException("passivation not supported");
+
+ sessions.remove(id);
+
+ cache.evict(getSessionFqn(id), true);
+ }
+
+ public Cache<Object, Object> getCache()
+ {
+ return cache;
+ }
+
+ public String getContextHostName()
+ {
+ return contextHostName;
+ }
+
+
+
+ // ----------------------------------------------------------- CacheListener
+
+
+ @NodeRemoved
+ public void nodeRemoved(NodeRemovedEvent event)
+ {
+ if (event.isPre())
+ return;
+
+ boolean local = event.isOriginLocal();
+ if (!fieldBased && local)
+ return;
+
+ @SuppressWarnings("unchecked")
+ Fqn<String> fqn = event.getFqn();
+ boolean isBuddy = FqnUtil.isBuddyFqn(fqn);
+
+ if (!local
+ && FqnUtil.isFqnSessionRootSized(fqn, isBuddy)
+ && FqnUtil.isFqnForOurWebapp(fqn, contextHostName, isBuddy))
+ {
+ // A session has been invalidated from another node;
+ // need to inform manager
+ String sessId = FqnUtil.getIdFromFqn(fqn, isBuddy);
+ removeSession(sessId, true, false);
+ }
+ else if (local && !isBuddy
+ && FqnUtil.isPossibleInternalPojoFqn(fqn)
+ && FqnUtil.isFqnForOurWebapp(fqn, contextHostName, isBuddy))
+ {
+ // One of our sessions' pojos is modified; need to inform
+ // the manager so it can mark the session dirty
+ String sessId = FqnUtil.getIdFromFqn(fqn, isBuddy);
+ notifyLocalAttributeModification(sessId);
+ }
+ }
+
+ @NodeModified
+ public void nodeModified(NodeModifiedEvent event)
+ {
+ if (event.isPre())
+ return;
+
+ boolean local = event.isOriginLocal();
+ if (!fieldBased && local)
+ return;
+
+ @SuppressWarnings("unchecked")
+ Fqn<String> fqn = event.getFqn();
+ boolean isBuddy = FqnUtil.isBuddyFqn(fqn);
+
+ if (!local
+ && FqnUtil.isFqnSessionRootSized(fqn, isBuddy)
+ && FqnUtil.isFqnForOurWebapp(fqn, contextHostName, isBuddy))
+ {
+ // Query if we have version value in the distributed cache.
+ // If we have a version value, compare the version and invalidate if necessary.
+ @SuppressWarnings("unchecked")
+ Map<Object, Object> data = event.getData();
+ AtomicInteger version = (AtomicInteger) data.get(VERSION);
+ if(version != null)
+ {
+ String realId = FqnUtil.getIdFromFqn(fqn, isBuddy);
+ String owner = isBuddy ? FqnUtil.getBuddyOwner(fqn) : null;
+ AtomicLong timestamp = (AtomicLong) data.get(TIMESTAMP);
+ if (timestamp == null)
+ {
+ log.warn("No timestamp attribute found in " + fqn);
+ }
+ else
+ {
+ // Notify the manager that a session has been updated
+ boolean updated = sessionChangedInDistributedCache(realId, owner,
+ version.get());
+ if (!updated && !isBuddy)
+ {
+ log.warn("Possible concurrency problem: Replicated version id " +
+ version + " is less than or equal to in-memory version for session " + realId);
+ }
+ /*else
+ {
+ We have a local session but got a modification for the buddy tree.
+ This means another node is in the process of taking over the session;
+ we don't worry about it
+ }
+ */
+ }
+ }
+ else if (!attributeBased) // other granularities can modify attributes only
+ {
+ log.warn("No version attribute found in " + fqn);
+ }
+ }
+ else if (local && !isBuddy
+ && FqnUtil.isPossibleInternalPojoFqn(fqn)
+ && FqnUtil.isFqnForOurWebapp(fqn, contextHostName, isBuddy))
+ {
+ // One of our sessions' pojos is modified; need to inform
+ // the manager so it can mark the session dirty
+ String sessId = FqnUtil.getIdFromFqn(fqn, isBuddy);
+ notifyLocalAttributeModification(sessId);
+ }
+ }
+
+ // ------------------------------------------------------------ Internal API
+
+ protected boolean isBatchStarted()
+ {
+ try
+ {
+ return tm.getTransaction() != null;
+ }
+ catch (SystemException e)
+ {
+ throw new RuntimeException("failed checking for tx", e);
+ }
+ }
+
+ protected void startBatch()
+ {
+ try
+ {
+ tm.begin();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("failed starting tx", e);
+ }
+ }
+
+ protected void endBatch()
+ {
+ try
+ {
+ tm.commit();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("failed committing tx", e);
+ }
+ }
+
+ protected Session findSession(String id)
+ {
+ Session session = sessions.get(id);
+ if (session == null || session.isOutdated())
+ {
+ session = loadSession(id);
+ if (session != null)
+ {
+ sessions.put(id, session);
+ }
+ }
+ return session;
+ }
+
+ protected Session createSession()
+ {
+ Session session = createEmptySession();
+ sessions.put(session.getId(), session);
+ return session;
+ }
+
+ protected Session removeSession(String id, boolean localOnly, boolean localCall)
+ {
+ Session session = sessions.remove(id);
+ if (localCall)
+ {
+ // TODO mock the bit where each individual attribute is removed first
+
+ // Remove the session node
+ if (localOnly)
+ {
+ cache.getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ }
+ cache.removeNode(getSessionFqn(id));
+ }
+
+ return session;
+ }
+
+ protected Granularity getGranularity()
+ {
+ return appMetadata.granularity;
+ }
+
+ private Fqn<String> getSessionFqn(String id)
+ {
+ return Fqn.fromRelativeElements(baseFqn, id);
+ }
+
+ private Session createEmptySession()
+ {
+ Session session = null;
+ switch (appMetadata.granularity)
+ {
+ case SESSION:
+ case ATTRIBUTE:
+ session = new Session(this);
+ break;
+ case FIELD:
+ throw new IllegalStateException("implement");
+ }
+ return session;
+ }
+
+ /**
+ * JBC read of a session.
+ */
+ private Session loadSession(String id)
+ {
+ Session session = null;
+
+ boolean startTx = !isBatchStarted();
+ if (startTx)
+ startBatch();
+ Map<Object, Object> data = null;
+ try
+ {
+ if (buddyReplication)
+ {
+ cache.getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
+ }
+ data = cache.getData(getSessionFqn(id));
+ }
+ finally
+ {
+ if (startTx)
+ endBatch();
+ }
+
+ if (data != null)
+ {
+ session = createEmptySession();
+ AtomicInteger version = (AtomicInteger) data.get(VERSION);
+ AtomicLong timestamp = (AtomicLong) data.get(TIMESTAMP);
+ SessionMetadata metadata = (SessionMetadata) data.get(METADATA);
+ Map<String, Object> attributes = loadSessionAttributes(id, data);
+ session.update(version, timestamp, metadata, attributes);
+ }
+ return session;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected Map<String, Object> loadSessionAttributes(String id, Map<Object, Object> sessionNodeData)
+ {
+ Map<String, Object> result = new HashMap<String, Object>();
+ switch (appMetadata.granularity)
+ {
+ case SESSION:
+ result.putAll((Map<String, Object>) sessionNodeData.get(ATTRIBUTES));
+ break;
+ case ATTRIBUTE:
+ for (Map.Entry<Object, Object> entry : sessionNodeData.entrySet())
+ {
+ if (entry.getKey() instanceof String)
+ {
+ result.put((String) entry.getKey(), entry.getValue());
+ }
+ }
+ break;
+ case FIELD:
+ throw new IllegalStateException("implement");
+ }
+
+ return result;
+ }
+
+ /**
+ * JBC write for granularity SESSION.
+ */
+ protected void storeSession(String id, AtomicInteger version, AtomicLong timestamp, SessionMetadata metadata, Map<String, Object> attributes)
+ {
+ if (version == null)
+ throw new IllegalArgumentException("version is null");
+ if (timestamp == null)
+ throw new IllegalArgumentException("timestamp is null");
+
+ Fqn<String> fqn = getSessionFqn(id);
+
+ Map<Object, Object> data = new HashMap<Object, Object>();
+ data.put(VERSION, version);
+ data.put(TIMESTAMP, timestamp);
+ if (metadata != null)
+ {
+ data.put(METADATA, metadata);
+ }
+ if (attributes != null)
+ {
+ data.put(ATTRIBUTES, attributes);
+ }
+
+ cache.put(fqn, data);
+ }
+
+ /**
+ * JBC write for granularity ATTRIBUTE.
+ */
+ protected void storeSession(String id, AtomicInteger version, AtomicLong timestamp, SessionMetadata metadata, Map<String, Object> modifiedAttributes, Set<String> removedAttributes)
+ {
+ storeSession(id, version, timestamp, metadata, null);
+
+ Fqn<String> fqn = getSessionFqn(id);
+
+ if (modifiedAttributes != null)
+ {
+ cache.put(fqn, modifiedAttributes);
+ }
+
+ if (removedAttributes != null)
+ {
+ for (String key : removedAttributes)
+ {
+ cache.remove(fqn, key);
+ }
+ }
+ }
+
+ private boolean sessionChangedInDistributedCache(String realId, String owner, int version)
+ {
+ Session session = sessions.get(realId);
+ if (session != null)
+ {
+ session.setOutdated(true);
+ if (session.getVersion().get() >= version)
+ return false;
+ }
+ return true;
+ }
+
+ private void notifyLocalAttributeModification(String sessId)
+ {
+ Session session = sessions.get(sessId);
+ if (session != null)
+ {
+ session.setOutdated(true);
+ }
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManagerSupport.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManagerSupport.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionManagerSupport.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,73 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.cache.CacheManager;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class SessionManagerSupport
+{
+ /**
+ * For each thread holds list of session managers created using this factory.
+ */
+ private static final ThreadLocal<List<SessionManager>> threadSessionManagers =
+ new ThreadLocal<List<SessionManager>>()
+ {
+ @Override
+ protected List<SessionManager> initialValue()
+ {
+ return new ArrayList<SessionManager>();
+ }
+ };
+
+ public static List<SessionManager> createSessionManagers(List<CacheManager> cacheManagers, WebAppMetadata metadata)
+ {
+ List<SessionManager> existing = threadSessionManagers.get();
+ existing.clear();
+ for (CacheManager cm : cacheManagers)
+ {
+ SessionManager sm = new SessionManager(cm, metadata);
+ existing.add(sm);
+ }
+
+ return new ArrayList<SessionManager>(existing);
+ }
+
+ public static void tearDown()
+ {
+ List<SessionManager> existing = threadSessionManagers.get();
+ for (SessionManager sm : existing)
+ {
+ if (sm.isStarted())
+ sm.stop();
+ }
+ existing.clear();
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionMetadata.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionMetadata.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SessionMetadata.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.io.Serializable;
+
+/**
+ * Metadata about a session that is only replicated infrequently.
+ *
+ * @author Brian Stansberry
+ */
+public class SessionMetadata implements Serializable
+{
+ /** The serialVersionUID */
+ private static final long serialVersionUID = 1L;
+
+ private static volatile int counter;
+
+ public final String id = String.valueOf(++counter);
+ public final long creationTime = System.currentTimeMillis();
+ public boolean valid = true;
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SetAttributesServlet.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SetAttributesServlet.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/SetAttributesServlet.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A Servlet that sets attributes on the session.
+ *
+ * @author Brian Stansberry
+ */
+public class SetAttributesServlet extends AbstractServlet
+{
+ private final Map<String, Object> toSet;
+
+ public SetAttributesServlet(Map<String, Object> toSet)
+ {
+ this.toSet = new HashMap<String, Object>(toSet);
+ }
+
+ public void handleRequest(Request request)
+ {
+ Session session = extractSession(request);
+ for (Map.Entry<String, Object> entry : toSet.entrySet())
+ {
+ session.setAttribute(entry.getKey(), entry.getValue());
+ }
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebAppMetadata.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebAppMetadata.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebAppMetadata.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+/**
+ * Metadata about a webapp; mocks the object created from a jboss-web.xml.
+ *
+ * @author Brian Stansberry
+ */
+public class WebAppMetadata
+{
+ public static final String DEFAULT_CACHE_CONFIG = "standard-session-cache";
+
+ public enum Granularity { SESSION, ATTRIBUTE, FIELD };
+
+ public final String warName;
+ public final String cacheConfigName;
+ public final boolean passivation;
+ public final Granularity granularity;
+
+ public WebAppMetadata(String warName)
+ {
+ this(warName, DEFAULT_CACHE_CONFIG, true, Granularity.SESSION);
+ }
+
+ public WebAppMetadata(String warName, String cacheConfigName, boolean passivation, Granularity granularity)
+ {
+ this.warName = warName;
+ this.cacheConfigName = cacheConfigName;
+ this.passivation = passivation;
+ this.granularity = granularity;
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebSessionTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebSessionTestBase.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/integration/websession/util/WebSessionTestBase.java 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,157 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.cache.integration.websession.util;
+
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheManager;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.integration.CacheManagerSupport;
+import org.jboss.cache.integration.UnitTestCacheFactoryConfigurationRegistry;
+import org.jboss.cache.integration.websession.util.WebAppMetadata.Granularity;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ * Base class that handles standard before/after class/method stuff.
+ *
+ * @author Brian Stansberry
+ */
+public abstract class WebSessionTestBase
+{
+ public static final String DEFAULT_CACHE_CONFIG_FILE_NAME = "configs/integration/web-session-cache-configs.xml";
+
+ private AtomicInteger testCount = new AtomicInteger();
+ private List<CacheManager> cacheManagers;
+ private List<SessionManager> sessionManagers;
+
+ @BeforeClass(alwaysRun = true)
+ public void beforeClass() throws Exception
+ {
+ cacheManagers = CacheManagerSupport.createCacheManagers(getNumCacheManagers(), getCacheConfigFileName(), getStacksXmlFileName());
+ if (getStartCachesInBeforeClass() && getCacheConfigName() != null)
+ {
+ for (CacheManager cm : cacheManagers)
+ {
+ Cache<Object, Object> cache = cm.getCache(getCacheConfigName(), true);
+ if (cache.getCacheStatus() != CacheStatus.STARTED)
+ cache.start();
+ }
+ }
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void afterClass()
+ {
+ CacheManagerSupport.tearDown();
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setup()
+ {
+ testCount.incrementAndGet();
+
+ if (getCreateManagersInSetup() && getWebAppMetaData() != null)
+ {
+ sessionManagers = SessionManagerSupport.createSessionManagers(cacheManagers, getWebAppMetaData());
+ for (SessionManager mgr : sessionManagers)
+ {
+ mgr.start();
+ }
+ }
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception
+ {
+ SessionManagerSupport.tearDown();
+ }
+
+ protected abstract int getNumCacheManagers();
+
+ protected String getCacheConfigFileName()
+ {
+ return DEFAULT_CACHE_CONFIG_FILE_NAME;
+ }
+
+ protected String getStacksXmlFileName()
+ {
+ return UnitTestCacheFactoryConfigurationRegistry.DEFAULT_STACKS_XML_RESOURCE;
+ }
+
+ protected boolean getStartCachesInBeforeClass()
+ {
+ return true;
+ }
+
+ protected abstract String getCacheConfigName();
+
+ protected boolean getCreateManagersInSetup()
+ {
+ return false;
+ }
+
+ protected boolean getUsePassivation()
+ {
+ return true;
+ }
+
+ protected Granularity getGranularity()
+ {
+ return Granularity.SESSION;
+ }
+
+ protected WebAppMetadata getWebAppMetaData()
+ {
+ return new WebAppMetadata(getWarNameForTest(), getCacheConfigName(), getUsePassivation(), getGranularity());
+ }
+
+ protected List<CacheManager> getCacheManagers()
+ {
+ return cacheManagers;
+ }
+
+ protected List<SessionManager> getSessionManagers()
+ {
+ return sessionManagers;
+ }
+
+ protected int getTestCount()
+ {
+ return testCount.get();
+ }
+
+ protected String getWarNameForTest()
+ {
+ return getClass().getSimpleName() + getTestCount();
+ }
+
+ protected Object getAttributeValue(int value)
+ {
+ return Integer.valueOf(value);
+ }
+}
Added: core/trunk/src/test/resources/configs/integration/hibernate-cache-configs.xml
===================================================================
--- core/trunk/src/test/resources/configs/integration/hibernate-cache-configs.xml (rev 0)
+++ core/trunk/src/test/resources/configs/integration/hibernate-cache-configs.xml 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,741 @@
+<cache-configs>
+
+ <!--
+ | Following are JBoss Cache configurations suitable for different
+ | Hibernate 2nd Level Cache uses (e.g. entities vs. queries).
+ |
+ | In all cases, TransactionManager configuration not required.
+ | Hibernate will plug in its own transaction manager integration.
+ -->
+
+
+ <!-- A config appropriate for entity/collection caching. -->
+ <cache-config name="optimistic-entity">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <!-- Mode of communication with peer caches.
+
+ INVALIDATION_SYNC is highly recommended as the mode for use
+ with entity and collection caches.
+ -->
+ <attribute name="CacheMode">INVALIDATION_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-optimistic-entity</attribute>
+
+ <!-- Use a UDP (multicast) based stack. A udp-sync stack might be
+ slightly better (no JGroups FC) but we stick with udp to
+ help ensure this cache and others like timestamps-cache
+ that require FC can use the same underlying JGroups resources. -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Whether or not to fetch state on joining a cluster. -->
+ <attribute name="FetchInMemoryState">false</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup. Ignored if FetchInMemoryState=false.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+ <!-- A config appropriate for entity/collection caching that
+ uses pessimistic locking -->
+ <cache-config name="pessimistic-entity">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+ <!--
+ READ_COMMITTED is as strong as necessary for most
+ 2nd Level Cache use cases.
+ -->
+ <attribute name="IsolationLevel">READ_COMMITTED</attribute>
+
+ <!-- Mode of communication with peer caches.
+
+ INVALIDATION_SYNC is highly recommended as the mode for use
+ with entity and collection caches.
+ -->
+ <attribute name="CacheMode">INVALIDATION_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-pessimistic-entity</attribute>
+
+ <!-- Use a UDP (multicast) based stack. A udp-sync stack might be
+ slightly better (no JGroups FC) but we stick with udp to
+ help ensure this cache and others like timestamps-cache
+ that require FC can use the same underlying JGroups resources. -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Whether or not to fetch state on joining a cluster. -->
+ <attribute name="FetchInMemoryState">false</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup. Ignored if FetchInMemoryState=false.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+
+ <!-- Same as "pessimistic-entity" but here we use REPEATABLE_READ
+ instead of READ_COMMITTED. REPEATABLE_READ is only useful if the
+ application evicts/clears entities from the Hibernate Session and
+ then expects to repeatably re-read them in the same transaction.
+ Otherwise, the Session's internal cache provides a repeatable-read
+ semantic. Before choosing this config, carefully read the docs
+ and make sure you really need REPEATABLE_READ.
+ -->
+ <cache-config name="pessimistic-entity-repeatable">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+ <!-- Here we use REPEATABLE_READ. -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Mode of communication with peer caches.
+
+ INVALIDATION_SYNC is highly recommended as the mode for use
+ with entity and collection caches.
+ -->
+ <attribute name="CacheMode">INVALIDATION_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-pessimistic-entity-rr</attribute>
+
+ <!-- Use a UDP (multicast) based stack. A udp-sync stack might be
+ slightly better (no JGroups FC) but we stick with udp to
+ help ensure this cache and others like timestamps-cache
+ that require FC can use the same underlying JGroups resources. -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Whether or not to fetch state on joining a cluster. -->
+ <attribute name="FetchInMemoryState">false</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup. Ignored if FetchInMemoryState=false.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+
+ <!-- A config appropriate for query caching. Does not replicate
+ queries. DO NOT STORE TIMESTAMPS IN THIS CACHE.
+ -->
+ <cache-config name="local-query">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <attribute name="CacheMode">LOCAL</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+ <!-- A query cache that replicates queries. Replication is asynchronous.
+ DO NOT STORE TIMESTAMPS IN THIS CACHE as no initial state transfer
+ is performed.
+ -->
+ <cache-config name="replicated-query">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <!-- Mode of communication with peer caches.
+
+ REPL_ASYNC means replicate but sender does not block waiting for
+ peers to acknowledge applying the change. Valid for queries as
+ the timestamp cache mechanism will allow Hibernate to discard
+ out-of-date queries.
+ -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-replicated-query</attribute>
+
+ <!-- Use a UDP (multicast) based stack -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Whether or not to fetch state on joining a cluster. -->
+ <attribute name="FetchInMemoryState">false</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup. Ignored if FetchInMemoryState=false.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+
+ <!-- Optimized for timestamp caching. A clustered timestamp cache
+ is required if query caching is used, even if the query cache
+ itself is configured with CacheMode=LOCAL.
+ -->
+ <cache-config name="timestamps-cache">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+ <!--
+ READ_COMMITTED is as strong as necessary.
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Cannot be INVALIDATION. ASYNC for improved performance. -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-timestamps-cache</attribute>
+
+ <!-- Use a UDP (multicast) based stack -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Used for timestamps, so must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup. Ignored if FetchInMemoryState=false.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+
+ <!-- A config appropriate for a cache that's shared for
+ entity, collection, query and timestamp caching. Not an advised
+ configuration, since it requires cache mode REPL_SYNC, which is the
+ least efficient mode. Also requires a full state transfer at startup,
+ which can be expensive. Uses optimistic locking -->
+ <cache-config name="optimistic-shared">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">OPTIMISTIC</attribute>
+
+ <!-- Must use REPL since used for timestamp caching.
+ Must use SYNC to maintain cache consistency for entities.
+ -->
+ <attribute name="CacheMode">REPL_SYNC</attribute>
+
+ <!-- With OPTIMISTIC with replication we need to use synchronous commits. -->
+ <attribute name="SyncCommitPhase">true</attribute>
+ <attribute name="SyncRollbackPhase">true</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-optimistic-shared</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because timestamp communication will not require a synchronous response.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Used for timestamps, so must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup. Ignored if FetchInMemoryState=false.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+
+ <!-- A config appropriate for a cache that's shared for
+ entity, collection, query and timestamp caching. Not an advised
+ configuration, since it requires cache mode REPL_SYNC, which is the
+ least efficient mode. Also requires a full state transfer at startup,
+ which can be expensive. Uses pessmistic locking.
+ -->
+ <cache-config name="pessimistic-shared">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+ <!--
+ READ_COMMITTED is as strong as necessary for most
+ 2nd Level Cache use cases.
+ -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Must use REPL since used for timestamp caching.
+ Must use SYNC to maintain cache consistency for entities.
+ -->
+ <attribute name="CacheMode">REPL_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-pessimistic-shared</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because timestamp communication will not require a synchronous response.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Used for timestamps, so must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server. Default is "false".
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+
+
+ <!-- Same as "pessimistic-shared" but here we use REPEATABLE_READ
+ instead of READ_COMMITTED. REPEATABLE_READ is only useful if the
+ application evicts/clears entities from the Hibernate Session and
+ then expects to repeatably re-read them in the same transaction.
+ Otherwise, the Session's internal cache provides a repeatable-read
+ semantic. Before choosing this config, carefully read the docs
+ and make sure you really need REPEATABLE_READ.
+ -->
+ <cache-config name="pessimistic-shared-repeatable">
+
+ <!-- Node locking scheme -->
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+
+ <!-- Here we use REPEATABLE_READ. -->
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Must use REPL since used for timestamp caching.
+ Must use SYNC to maintain cache coherency for entities.
+ -->
+ <attribute name="CacheMode">REPL_SYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-pessimistic-shared-rr</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because timestamp communication will not require a synchronous response.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Used for timestamps, so must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">20000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">20000</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <!-- Eviction policy configurations. -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
+ <!-- Cache wide default -->
+ <region name="/_default_">
+ <!-- Evict LRU node once we have more than this number of nodes -->
+ <attribute name="maxNodes">10000</attribute>
+ <!-- And, evict any node that hasn't been accessed in this many seconds -->
+ <attribute name="timeToLiveSeconds">1000</attribute>
+ <!-- Don't evict a node that's been accessed within this many seconds.
+ Set this to a value greater than your max expected transaction length. -->
+ <attribute name="minTimeToLiveSeconds">120</attribute>
+ </region>
+ <!-- Don't ever evict modification timestamps -->
+ <region name="/TS" policyClass="org.jboss.cache.eviction.NullEvictionPolicy"/>
+ </config>
+ </attribute>
+
+ </cache-config>
+
+</cache-configs>
Added: core/trunk/src/test/resources/configs/integration/jgroups-channelfactory-stacks.xml
===================================================================
--- core/trunk/src/test/resources/configs/integration/jgroups-channelfactory-stacks.xml (rev 0)
+++ core/trunk/src/test/resources/configs/integration/jgroups-channelfactory-stacks.xml 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,378 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE protocol_stacks [
+ <!ENTITY shared-udp '
+ <!-- UDP transport config meant to be shared between different channels
+ with different requirements. Message bundling is disabled in this
+ general-purpose config as it can add latency to synchronous RPCs. -->
+ <UDP
+ mcast_port="${jboss.jgroups.udp.mcast_port:45688}"
+ mcast_addr="${jgroups.udp.mcast_addr:228.11.11.11}"
+ tos="8"
+ ucast_recv_buf_size="20000000"
+ ucast_send_buf_size="640000"
+ mcast_recv_buf_size="25000000"
+ mcast_send_buf_size="640000"
+ loopback="true"
+ discard_incompatible_packets="true"
+ enable_bundling="false"
+ max_bundle_size="64000"
+ max_bundle_timeout="30"
+ use_incoming_packet_handler="true"
+ ip_ttl="2"
+ thread_naming_pattern="cl"
+ timer.num_threads="12"
+
+ use_concurrent_stack="true"
+
+ thread_pool.enabled="true"
+ thread_pool.min_threads="20"
+ thread_pool.max_threads="200"
+ thread_pool.keep_alive_time="5000"
+ thread_pool.queue_enabled="true"
+ thread_pool.queue_max_size="1000"
+ thread_pool.rejection_policy="discard"
+
+ oob_thread_pool.enabled="true"
+ oob_thread_pool.min_threads="1"
+ oob_thread_pool.max_threads="20"
+ oob_thread_pool.keep_alive_time="5000"
+ oob_thread_pool.queue_enabled="false"
+ oob_thread_pool.queue_max_size="100"
+ oob_thread_pool.rejection_policy="run"/>
+ '>
+]>
+
+
+<!--
+ Standard JGroups protocol stacks definitions, used by the JChannelFactory bean.
+
+ Author: Bela Ban, Brian Stansberry
+ Version: $Id:jgroups-channelfactory-stacks.xml 71313 2008-03-26 19:46:59Z bstansberry(a)jboss.com $
+-->
+<protocol_stacks>
+ <stack name="udp"
+ description="Default: IP multicast based stack, with flow control.">
+ <config>
+ <!-- UDP transport config meant to be shared between different channels,
+ including a JBoss Messaging channel that uses the 'jbm-control'
+ stack listed below. Message bundling is disabled, as it can add
+ latency to synchronous group RPCs. Services that only make
+ asynchronous RPCs (e.g. JBoss Cache configured for REPL_ASYNC)
+ and do so in high volume may be able to improve performance by
+ configuring their cache to use the udp-async stack below.
+ Services that only make synchronous RPCs (e.g. JBoss Cache
+ configured for REPL_SYNC or INVALIDATION_SYNC) may be able
+ to improve performance by using the udp-sync stack below, which
+ does not include flow control.
+
+ The UDP config is included via an XML entity to ensure that
+ it remains consistent between this stack and the 'jbm-control'
+ stack below.
+ -->
+ &shared-udp;
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 max_interval="100000" min_interval="20000"/>
+ <FD_SOCK/>
+ <FD timeout="6000" max_tries="5" shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK use_mcast_xmit="false" gc_lag="0"
+ retransmit_timeout="300,600,1200,2400,4800"
+ discard_delivered_msgs="true"/>
+ <UNICAST timeout="300,600,1200,2400,3600"/>
+ <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
+ max_bytes="400000"/>
+ <pbcast.GMS print_local_addr="true" join_timeout="3000"
+ shun="true"
+ view_bundling="true"
+ view_ack_collection_timeout="5000"/>
+ <FC max_credits="2000000" min_threshold="0.10"/>
+ <FRAG2 frag_size="60000"/>
+ <!-- pbcast.STREAMING_STATE_TRANSFER use_reading_thread="true"/ -->
+ <pbcast.STATE_TRANSFER/>
+ <pbcast.FLUSH timeout="0"/>
+ </config>
+ </stack>
+
+
+ <stack name="udp-async"
+ description="Same as the default 'udp' stack above, except message bundling
+ is enabled in the transport protocol (enable_bundling=true).
+ Useful for services that make high-volume asynchronous
+ RPCs (e.g. high volume JBoss Cache instances configured
+ for REPL_ASYNC) where message bundling may improve performance.">
+ <config>
+ <UDP
+ mcast_port="${jboss.jgroups.udp_async.mcast_port:45689}"
+ mcast_addr="${jgroups.udp.mcast_addr:228.11.11.11}"
+ tos="8"
+ ucast_recv_buf_size="20000000"
+ ucast_send_buf_size="640000"
+ mcast_recv_buf_size="25000000"
+ mcast_send_buf_size="640000"
+ loopback="true"
+ discard_incompatible_packets="true"
+ enable_bundling="false"
+ max_bundle_size="64000"
+ max_bundle_timeout="30"
+ use_incoming_packet_handler="true"
+ ip_ttl="2"
+ thread_naming_pattern="cl"
+ timer.num_threads="12"
+
+ use_concurrent_stack="true"
+
+ thread_pool.enabled="true"
+ thread_pool.min_threads="8"
+ thread_pool.max_threads="200"
+ thread_pool.keep_alive_time="5000"
+ thread_pool.queue_enabled="true"
+ thread_pool.queue_max_size="1000"
+ thread_pool.rejection_policy="discard"
+
+ oob_thread_pool.enabled="true"
+ oob_thread_pool.min_threads="1"
+ oob_thread_pool.max_threads="8"
+ oob_thread_pool.keep_alive_time="5000"
+ oob_thread_pool.queue_enabled="false"
+ oob_thread_pool.queue_max_size="100"
+ oob_thread_pool.rejection_policy="run"/>
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 max_interval="100000" min_interval="20000"/>
+ <FD_SOCK/>
+ <FD timeout="6000" max_tries="5" shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK use_mcast_xmit="false" gc_lag="0"
+ retransmit_timeout="300,600,1200,2400,4800"
+ discard_delivered_msgs="true"/>
+ <UNICAST timeout="300,600,1200,2400,3600"/>
+ <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
+ max_bytes="400000"/>
+ <pbcast.GMS print_local_addr="true" join_timeout="3000"
+ shun="true"
+ view_bundling="true"
+ view_ack_collection_timeout="5000"/>
+ <FC max_credits="2000000" min_threshold="0.10"/>
+ <FRAG2 frag_size="60000"/>
+ <!-- pbcast.STREAMING_STATE_TRANSFER use_reading_thread="true"/ -->
+ <pbcast.STATE_TRANSFER/>
+ <pbcast.FLUSH timeout="0"/>
+ </config>
+ </stack>
+
+
+ <stack name="udp-sync"
+ description="IP multicast based stack, without flow control and
+ without message bundling. This should be used instead
+ of 'udp' if (1) synchronous calls are used and (2) the
+ message volume (rate and size) is not that large. Don't
+ use this configuration if you send messages at a high
+ sustained rate, or you might run out of memory">
+ <config>
+ <UDP
+ mcast_port="${jgroups.udp_sync.mcast_port:45699}"
+ mcast_addr="${jgroups.udp.mcast_addr:229.11.11.11}"
+ tos="8"
+ ucast_recv_buf_size="20000000"
+ ucast_send_buf_size="640000"
+ mcast_recv_buf_size="25000000"
+ mcast_send_buf_size="640000"
+ loopback="true"
+ discard_incompatible_packets="true"
+ enable_bundling="false"
+ max_bundle_size="64000"
+ max_bundle_timeout="30"
+ use_incoming_packet_handler="true"
+ ip_ttl="2"
+
+ use_concurrent_stack="true"
+
+ thread_pool.enabled="true"
+ thread_pool.min_threads="8"
+ thread_pool.max_threads="200"
+ thread_pool.keep_alive_time="5000"
+ thread_pool.queue_enabled="true"
+ thread_pool.queue_max_size="1000"
+ thread_pool.rejection_policy="discard"
+
+ oob_thread_pool.enabled="true"
+ oob_thread_pool.min_threads="1"
+ oob_thread_pool.max_threads="8"
+ oob_thread_pool.keep_alive_time="5000"
+ oob_thread_pool.queue_enabled="false"
+ oob_thread_pool.queue_max_size="100"
+ oob_thread_pool.rejection_policy="run"/>
+ <PING timeout="2000" num_initial_members="3"/>
+ <MERGE2 max_interval="100000" min_interval="20000"/>
+ <FD_SOCK/>
+ <FD timeout="6000" max_tries="5" shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK use_mcast_xmit="false" gc_lag="0"
+ retransmit_timeout="300,600,1200,2400,4800"
+ discard_delivered_msgs="true"/>
+ <UNICAST timeout="300,600,1200,2400,3600"/>
+ <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
+ max_bytes="400000"/>
+ <pbcast.GMS print_local_addr="true" join_timeout="3000"
+ shun="true"
+ view_bundling="true"
+ view_ack_collection_timeout="5000"/>
+ <FRAG2 frag_size="60000"/>
+ <!--pbcast.STREAMING_STATE_TRANSFER use_reading_thread="true"/ -->
+ <pbcast.STATE_TRANSFER/>
+ <pbcast.FLUSH timeout="0"/>
+ </config>
+ </stack>
+
+
+ <stack name="tcp"
+ description="TCP based stack, with flow control and message bundling.
+ This is usually used when IP multicasting cannot be used
+ in a network, e.g. because it is disabled (e.g. routers
+ discard multicast)">
+ <config>
+ <TCP
+ start_port="7600"
+ tcp_nodelay="true"
+ loopback="false"
+ recv_buf_size="20000000"
+ send_buf_size="640000"
+ discard_incompatible_packets="true"
+ max_bundle_size="64000"
+ max_bundle_timeout="30"
+ use_incoming_packet_handler="true"
+ enable_bundling="true"
+ use_send_queues="false"
+ sock_conn_timeout="300"
+ skip_suspected_members="true"
+ timer.num_threads="12"
+
+ use_concurrent_stack="true"
+
+ thread_pool.enabled="true"
+ thread_pool.min_threads="20"
+ thread_pool.max_threads="200"
+ thread_pool.keep_alive_time="5000"
+ thread_pool.queue_enabled="true"
+ thread_pool.queue_max_size="1000"
+ thread_pool.rejection_policy="discard"
+
+ oob_thread_pool.enabled="true"
+ oob_thread_pool.min_threads="1"
+ oob_thread_pool.max_threads="20"
+ oob_thread_pool.keep_alive_time="5000"
+ oob_thread_pool.queue_enabled="false"
+ oob_thread_pool.queue_max_size="100"
+ oob_thread_pool.rejection_policy="run"/>
+ <!-- Alternative 1: multicast-based automatic discovery. -->
+ <MPING timeout="3000"
+ num_initial_members="3"
+ mcast_addr="${jgroups.udp.mcast_addr:230.11.11.11}"
+ mcast_port="${jgroups.tcp_mping.mcast_port:45700}"
+ ip_ttl="2"/>
+ <!-- Alternative 2: non multicast-based replacement for MPING. Requires a static configuration
+ of *all* possible cluster members.
+ <TCPPING timeout="3000"
+ initial_hosts="${jgroups.tcpping.initial_hosts:localhost[7600],localhost[7601]}"
+ port_range="1"
+ num_initial_members="3"/>
+ -->
+ <MERGE2 max_interval="100000" min_interval="20000"/>
+ <FD_SOCK/>
+ <FD timeout="6000" max_tries="5" shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK use_mcast_xmit="false" gc_lag="0"
+ retransmit_timeout="300,600,1200,2400,4800"
+ discard_delivered_msgs="true"/>
+ <UNICAST timeout="300,600,1200,2400,3600"/>
+ <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
+ max_bytes="400000"/>
+ <pbcast.GMS print_local_addr="true" join_timeout="3000"
+ shun="true"
+ view_bundling="true"
+ view_ack_collection_timeout="5000"/>
+ <FC max_credits="2000000" min_threshold="0.10"/>
+ <FRAG2 frag_size="60000"/>
+ <!-- pbcast.STREAMING_STATE_TRANSFER use_reading_thread="true"/ -->
+ <pbcast.STATE_TRANSFER/>
+ <pbcast.FLUSH timeout="0"/>
+ </config>
+ </stack>
+
+
+ <stack name="tcp-sync"
+ description="TCP based stack, without flow control and without
+ message bundling. This is usually used when IP
+ multicasting cannot be used in a network (e.g.routers
+ discard multicast). This configuration should be used
+ instead of 'tcp' above when (1) synchronous calls are
+ used and (2) the message volume (rate and size) is not
+ that large.">
+ <config>
+ <TCP
+ start_port="7650"
+ tcp_nodelay="true"
+ loopback="false"
+ recv_buf_size="20000000"
+ send_buf_size="640000"
+ discard_incompatible_packets="true"
+ max_bundle_size="64000"
+ max_bundle_timeout="30"
+ use_incoming_packet_handler="true"
+ enable_bundling="false"
+ use_send_queues="false"
+ sock_conn_timeout="300"
+ skip_suspected_members="true"
+
+ use_concurrent_stack="true"
+
+ thread_pool.enabled="true"
+ thread_pool.min_threads="8"
+ thread_pool.max_threads="200"
+ thread_pool.keep_alive_time="5000"
+ thread_pool.queue_enabled="true"
+ thread_pool.queue_max_size="1000"
+ thread_pool.rejection_policy="discard"
+
+ oob_thread_pool.enabled="true"
+ oob_thread_pool.min_threads="1"
+ oob_thread_pool.max_threads="8"
+ oob_thread_pool.keep_alive_time="5000"
+ oob_thread_pool.queue_enabled="false"
+ oob_thread_pool.queue_max_size="100"
+ oob_thread_pool.rejection_policy="run"/>
+ <!-- Alternative 1: multicast-based automatic discovery. -->
+ <MPING timeout="3000"
+ num_initial_members="3"
+ mcast_addr="${jgroups.udp.mcast_addr:231.11.11.11}"
+ mcast_port="${jgroups.tcp_sync_mping.mcast_port:45701}"
+ ip_ttl="2"/>
+ <!-- Alternative 2: non multicast-based replacement for MPING. Requires a static configuration
+ of all possible cluster members.
+ <TCPPING timeout="3000"
+ initial_hosts="${jgroups.tcpping.initial_hosts:localhost[7650],localhost[7651]}"
+ port_range="1"
+ num_initial_members="3"/>
+ -->
+ <MERGE2 max_interval="100000" min_interval="20000"/>
+ <FD_SOCK/>
+ <FD timeout="6000" max_tries="5" shun="true"/>
+ <VERIFY_SUSPECT timeout="1500"/>
+ <pbcast.NAKACK use_mcast_xmit="false" gc_lag="0"
+ retransmit_timeout="300,600,1200,2400,4800"
+ discard_delivered_msgs="true"/>
+ <UNICAST timeout="300,600,1200,2400,3600"/>
+ <pbcast.STABLE stability_delay="1000" desired_avg_gossip="50000"
+ max_bytes="400000"/>
+ <pbcast.GMS print_local_addr="true" join_timeout="3000"
+ shun="true"
+ view_bundling="true"
+ view_ack_collection_timeout="5000"/>
+ <!-- pbcast.STREAMING_STATE_TRANSFER use_reading_thread="true"/ -->
+ <pbcast.STATE_TRANSFER/>
+ <pbcast.FLUSH timeout="0"/>
+ </config>
+ </stack>
+
+</protocol_stacks>
+
+
Added: core/trunk/src/test/resources/configs/integration/sfsb-cache-configs.xml
===================================================================
--- core/trunk/src/test/resources/configs/integration/sfsb-cache-configs.xml (rev 0)
+++ core/trunk/src/test/resources/configs/integration/sfsb-cache-configs.xml 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,263 @@
+<cache-configs>
+
+ <!--
+ | A config appropriate for EJB3 SFSB caching.
+ -->
+ <cache-config name="sfsb-cache">
+ <!-- No transaction manager lookup -->
+
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-SFSBCache</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because we are using asynchronous replication.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">60000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">17500</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ SFSBs use region-based marshalling to provide for partial state
+ transfer during deployment/undeployment.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <attribute name="ExposeManagementStatistics">true</attribute>
+
+ <!-- Buddy Replication config -->
+ <attribute name="BuddyReplicationConfig">
+ <config>
+ <buddyReplicationEnabled>false</buddyReplicationEnabled>
+ <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
+ <!-- numBuddies is the number of backup nodes each node maintains.
+ ignoreColocatedBuddies means that each node will *try* to
+ select a buddy on a different physical host. If not able to do
+ so though, it will fall back to colocated nodes. -->
+ <buddyLocatorProperties>
+ numBuddies = 1
+ ignoreColocatedBuddies = true
+ </buddyLocatorProperties>
+
+ <!-- A way to specify a preferred replication group. If specified,
+ we try and pick a buddy why shares the same pool name (falling
+ back to other buddies if not available). This allows the sysdmin
+ to hint at backup buddies are picked, so for example, nodes may
+ be hinted topick buddies on a different physical rack or power
+ supply for added fault tolerance.
+ -->
+ <buddyPoolName>default</buddyPoolName>
+ <!-- communication timeout for inter-buddy group organisation
+ messages (such as assigning to and removing from groups -->
+ <buddyCommunicationTimeout>17500</buddyCommunicationTimeout>
+
+ <!-- Do not change these -->
+ <autoDataGravitation>false</autoDataGravitation>
+ <dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
+ <dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
+
+ </config>
+ </attribute>
+
+ <!-- Cache Loader for session passivation -->
+ <attribute name="CacheLoaderConfig">
+ <config>
+ <passivation>true</passivation>
+ <shared>false</shared>
+
+ <purgeOnStartup>true</purgeOnStartup>
+
+ <cacheloader>
+ <class>org.jboss.cache.loader.FileCacheLoader</class>
+ <properties>
+ location=${java.io.tmpdir}${/}sfsb
+ </properties>
+ <async>false</async>
+ <fetchPersistentState>true</fetchPersistentState>
+ <ignoreModifications>false</ignoreModifications>
+ <checkCharacterPortability>false</checkCharacterPortability>
+ </cacheloader>
+
+ </config>
+ </attribute>
+
+ <!-- SFSBs use JBoss Cache eviction -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.NullEvictionPolicy</attribute>
+ <!-- Cache wide default region -->
+ <region name="/_default_"/>
+ <!-- EJB3 integration code will programatically create
+ other regions as beans are deployed -->
+ </config>
+ </attribute>
+
+ </cache-config>
+
+ <!--
+ | A buddy replication enabled config appropriate for EJB3 SFSB caching.
+ -->
+ <cache-config name="br-sfsb-cache">
+ <!-- No transaction manager lookup -->
+
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-SFSBCache</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because we are using asynchronous replication.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">60000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">17500</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ SFSBs use region-based marshalling to provide for partial state
+ transfer during deployment/undeployment.
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <attribute name="ExposeManagementStatistics">true</attribute>
+
+ <!-- Buddy Replication config -->
+ <attribute name="BuddyReplicationConfig">
+ <config>
+ <buddyReplicationEnabled>true</buddyReplicationEnabled>
+ <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
+ <!-- numBuddies is the number of backup nodes each node maintains.
+ ignoreColocatedBuddies means that each node will *try* to
+ select a buddy on a different physical host. If not able to do
+ so though, it will fall back to colocated nodes. -->
+ <buddyLocatorProperties>
+ numBuddies = 1
+ ignoreColocatedBuddies = true
+ </buddyLocatorProperties>
+
+ <!-- A way to specify a preferred replication group. If specified,
+ we try and pick a buddy why shares the same pool name (falling
+ back to other buddies if not available). This allows the sysdmin
+ to hint at backup buddies are picked, so for example, nodes may
+ be hinted topick buddies on a different physical rack or power
+ supply for added fault tolerance.
+ -->
+ <buddyPoolName>default</buddyPoolName>
+ <!-- communication timeout for inter-buddy group organisation
+ messages (such as assigning to and removing from groups -->
+ <buddyCommunicationTimeout>17500</buddyCommunicationTimeout>
+
+ <!-- Do not change these -->
+ <autoDataGravitation>false</autoDataGravitation>
+ <dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
+ <dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
+
+ </config>
+ </attribute>
+
+ <!-- Cache Loader for session passivation -->
+ <attribute name="CacheLoaderConfig">
+ <config>
+ <passivation>true</passivation>
+ <shared>false</shared>
+
+ <purgeOnStartup>true</purgeOnStartup>
+
+ <cacheloader>
+ <class>org.jboss.cache.loader.FileCacheLoader</class>
+ <properties>
+ location=${java.io.tmpdir}${/}sfsb
+ </properties>
+ <async>false</async>
+ <fetchPersistentState>true</fetchPersistentState>
+ <ignoreModifications>false</ignoreModifications>
+ <checkCharacterPortability>false</checkCharacterPortability>
+ </cacheloader>
+
+ </config>
+ </attribute>
+
+ <!-- SFSBs use JBoss Cache eviction -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.NullEvictionPolicy</attribute>
+ <!-- Cache wide default region -->
+ <region name="/_default_"/>
+ <!-- EJB3 integration code will programatically create
+ other regions as beans are deployed -->
+ </config>
+ </attribute>
+
+ </cache-config>
+
+</cache-configs>
Added: core/trunk/src/test/resources/configs/integration/web-session-cache-configs.xml
===================================================================
--- core/trunk/src/test/resources/configs/integration/web-session-cache-configs.xml (rev 0)
+++ core/trunk/src/test/resources/configs/integration/web-session-cache-configs.xml 2008-11-24 07:01:36 UTC (rev 7186)
@@ -0,0 +1,372 @@
+<cache-configs>
+
+ <!--
+ | A config appropriate for HttpSession caches.
+ | Not for use with FIELD replication granularity webapps.
+ -->
+ <cache-config name="standard-session-cache">
+
+ <attribute name="TransactionManagerLookupClass">org.jboss.cache.transaction.BatchModeTransactionManagerLookup</attribute>
+
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Valid modes are REPL_ASYNC and REPL_SYNC -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-SessionCache</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because we are using asynchronous replication.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">60000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">17500</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!-- Region-based marshalling is not needed. -->
+ <attribute name="UseRegionBasedMarshalling">false</attribute>
+ <!-- Must match the value of "UseRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">false</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <attribute name="ExposeManagementStatistics">true</attribute>
+
+ <!-- Buddy Replication config -->
+ <attribute name="BuddyReplicationConfig">
+ <config>
+ <buddyReplicationEnabled>false</buddyReplicationEnabled>
+ <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
+ <!-- numBuddies is the number of backup nodes each node maintains.
+ ignoreColocatedBuddies means that each node will *try* to
+ select a buddy on a different physical host. If not able to do
+ so though, it will fall back to colocated nodes. -->
+ <buddyLocatorProperties>
+ numBuddies = 1
+ ignoreColocatedBuddies = true
+ </buddyLocatorProperties>
+
+ <!-- A way to specify a preferred replication group. If specified,
+ we try and pick a buddy why shares the same pool name (falling
+ back to other buddies if not available). This allows the sysdmin
+ to hint at backup buddies are picked, so for example, nodes may
+ be hinted topick buddies on a different physical rack or power
+ supply for added fault tolerance.
+ -->
+ <buddyPoolName>default</buddyPoolName>
+ <!-- communication timeout for inter-buddy group organisation
+ messages (such as assigning to and removing from groups -->
+ <buddyCommunicationTimeout>17500</buddyCommunicationTimeout>
+
+ <!-- Do not change these -->
+ <autoDataGravitation>false</autoDataGravitation>
+ <dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
+ <dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
+
+ </config>
+ </attribute>
+
+ <!-- Cache Loader for session passivation -->
+ <attribute name="CacheLoaderConfig">
+ <config>
+ <passivation>true</passivation>
+ <shared>false</shared>
+
+ <purgeOnStartup>true</purgeOnStartup>
+
+ <cacheloader>
+ <class>org.jboss.cache.loader.FileCacheLoader</class>
+ <properties>
+ location=${java.io.tmpdir}${/}session
+ </properties>
+ <async>false</async>
+ <fetchPersistentState>true</fetchPersistentState>
+ <ignoreModifications>false</ignoreModifications>
+ <checkCharacterPortability>false</checkCharacterPortability>
+ </cacheloader>
+
+ </config>
+ </attribute>
+
+ <!--
+ JBoss Cache eviction is not needed; webapp or SFSB container
+ manages eviction by itself.
+ -->
+
+ </cache-config>
+
+ <!--
+ | A config appropriate for HttpSession caches for webapps
+ | that use FIELD replication granularity.
+ -->
+ <cache-config name="field-granularity-session-cache">
+
+ <attribute name="TransactionManagerLookupClass">org.jboss.cache.transaction.BatchModeTransactionManagerLookup</attribute>
+
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Valid modes are LOCAL
+ REPL_ASYNC
+ REPL_SYNC
+ -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-FieldSessionCache</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because we are using asynchronous replication.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">60000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">17500</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!--
+ Indicate whether to use marshalling or not. Set this to true if you
+ are running under a scoped class loader, e.g., inside an application
+ server. Default is "false".
+ -->
+ <attribute name="UseRegionBasedMarshalling">true</attribute>
+ <!-- Must match the value of "useRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">true</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <attribute name="ExposeManagementStatistics">true</attribute>
+
+ <!-- Buddy Replication config -->
+ <attribute name="BuddyReplicationConfig">
+ <config>
+ <buddyReplicationEnabled>false</buddyReplicationEnabled>
+ <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
+ <!-- numBuddies is the number of backup nodes each node maintains.
+ ignoreColocatedBuddies means that each node will *try* to
+ select a buddy on a different physical host. If not able to do
+ so though, it will fall back to colocated nodes. -->
+ <buddyLocatorProperties>
+ numBuddies = 1
+ ignoreColocatedBuddies = true
+ </buddyLocatorProperties>
+
+ <!-- A way to specify a preferred replication group. If specified,
+ we try and pick a buddy why shares the same pool name (falling
+ back to other buddies if not available). This allows the sysdmin
+ to hint at backup buddies are picked, so for example, nodes may
+ be hinted topick buddies on a different physical rack or power
+ supply for added fault tolerance.
+ -->
+ <buddyPoolName>default</buddyPoolName>
+ <!-- communication timeout for inter-buddy group organisation
+ messages (such as assigning to and removing from groups -->
+ <buddyCommunicationTimeout>17500</buddyCommunicationTimeout>
+
+ <!-- Do not change these -->
+ <autoDataGravitation>false</autoDataGravitation>
+ <dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
+ <dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
+
+ </config>
+ </attribute>
+
+ <!-- Cache Loader for session passivation -->
+ <attribute name="CacheLoaderConfig">
+ <config>
+ <passivation>true</passivation>
+ <shared>false</shared>
+
+ <purgeOnStartup>true</purgeOnStartup>
+
+ <cacheloader>
+ <class>org.jboss.cache.loader.FileCacheLoader</class>
+ <properties>
+ location=${java.io.tmpdir}${/}field-session
+ </properties>
+ <async>false</async>
+ <fetchPersistentState>true</fetchPersistentState>
+ <ignoreModifications>false</ignoreModifications>
+ <checkCharacterPortability>false</checkCharacterPortability>
+ </cacheloader>
+
+ </config>
+ </attribute>
+
+ <!-- FIELD granularity webapps use JBoss Cache eviction -->
+ <attribute name="EvictionPolicyConfig">
+ <config>
+ <attribute name="wakeUpIntervalSeconds">5</attribute>
+ <!-- Name of the DEFAULT eviction policy class. -->
+ <attribute name="policyClass">org.jboss.cache.eviction.NullEvictionPolicy</attribute>
+ <!-- Cache wide default region -->
+ <region name="/_default_"/>
+ <!-- JBossWeb integration code will programatically create
+ other regions as webapps are deployed -->
+ </config>
+ </attribute>
+
+ </cache-config>
+
+ <!--
+ | A buddy replication enabled config appropriate for HttpSession caches.
+ | Not for use with FIELD replication granularity webapps.
+ -->
+ <cache-config name="br-standard-session-cache">
+
+ <attribute name="TransactionManagerLookupClass">org.jboss.cache.transaction.BatchModeTransactionManagerLookup</attribute>
+
+ <attribute name="NodeLockingScheme">PESSIMISTIC</attribute>
+ <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+
+ <!-- Valid modes are REPL_ASYNC and REPL_SYNC -->
+ <attribute name="CacheMode">REPL_ASYNC</attribute>
+
+ <!-- Name of cluster. Needs to be the same for all members, in order
+ to find each other -->
+ <attribute name="ClusterName">${jboss.partition.name:JBCTest}-SessionCache</attribute>
+
+ <!-- Use a UDP (multicast) based stack. Need JGroups flow control (FC)
+ because we are using asynchronous replication.
+ -->
+ <attribute name="MultiplexerStack">${jboss.default.jgroups.stack:udp}</attribute>
+
+ <!-- Must fetch state. -->
+ <attribute name="FetchInMemoryState">true</attribute>
+
+ <!--
+ The max amount of time (in milliseconds) we wait until the
+ state (ie. the contents of the cache) are retrieved from
+ existing members at startup.
+ -->
+ <attribute name="StateRetrievalTimeout">60000</attribute>
+
+ <!--
+ Number of milliseconds to wait until all responses for a
+ synchronous call have been received.
+ -->
+ <attribute name="SyncReplTimeout">17500</attribute>
+
+ <!-- Max number of milliseconds to wait for a lock acquisition -->
+ <attribute name="LockAcquisitionTimeout">15000</attribute>
+
+ <!-- Region-based marshalling is not needed. -->
+ <attribute name="UseRegionBasedMarshalling">false</attribute>
+ <!-- Must match the value of "UseRegionBasedMarshalling" -->
+ <attribute name="InactiveOnStartup">false</attribute>
+
+ <!-- Disable asynchronous RPC marshalling/sending -->
+ <attribute name="SerializationExecutorPoolSize">0</attribute>
+
+ <!-- We have no asynchronous notification listeners -->
+ <attribute name="ListenerAsyncPoolSize">0</attribute>
+
+ <attribute name="ExposeManagementStatistics">true</attribute>
+
+ <!-- Buddy Replication config -->
+ <attribute name="BuddyReplicationConfig">
+ <config>
+ <buddyReplicationEnabled>true</buddyReplicationEnabled>
+ <buddyLocatorClass>org.jboss.cache.buddyreplication.NextMemberBuddyLocator</buddyLocatorClass>
+ <!-- numBuddies is the number of backup nodes each node maintains.
+ ignoreColocatedBuddies means that each node will *try* to
+ select a buddy on a different physical host. If not able to do
+ so though, it will fall back to colocated nodes. -->
+ <buddyLocatorProperties>
+ numBuddies = 1
+ ignoreColocatedBuddies = true
+ </buddyLocatorProperties>
+
+ <!-- A way to specify a preferred replication group. If specified,
+ we try and pick a buddy why shares the same pool name (falling
+ back to other buddies if not available). This allows the sysdmin
+ to hint at backup buddies are picked, so for example, nodes may
+ be hinted topick buddies on a different physical rack or power
+ supply for added fault tolerance.
+ -->
+ <buddyPoolName>default</buddyPoolName>
+ <!-- communication timeout for inter-buddy group organisation
+ messages (such as assigning to and removing from groups -->
+ <buddyCommunicationTimeout>17500</buddyCommunicationTimeout>
+
+ <!-- Do not change these -->
+ <autoDataGravitation>false</autoDataGravitation>
+ <dataGravitationRemoveOnFind>true</dataGravitationRemoveOnFind>
+ <dataGravitationSearchBackupTrees>true</dataGravitationSearchBackupTrees>
+
+ </config>
+ </attribute>
+
+ <!-- Cache Loader for session passivation -->
+ <attribute name="CacheLoaderConfig">
+ <config>
+ <passivation>true</passivation>
+ <shared>false</shared>
+
+ <purgeOnStartup>true</purgeOnStartup>
+
+ <cacheloader>
+ <class>org.jboss.cache.loader.FileCacheLoader</class>
+ <properties>
+ location=${java.io.tmpdir}${/}session
+ </properties>
+ <async>false</async>
+ <fetchPersistentState>true</fetchPersistentState>
+ <ignoreModifications>false</ignoreModifications>
+ <checkCharacterPortability>false</checkCharacterPortability>
+ </cacheloader>
+
+ </config>
+ </attribute>
+
+ <!--
+ JBoss Cache eviction is not needed; webapp or SFSB container
+ manages eviction by itself.
+ -->
+
+ </cache-config>
+
+</cache-configs>
16 years, 1 month
JBoss Cache SVN: r7185 - in core/trunk/src/test/java/org/jboss/cache: options/cachemodelocal and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: mircea.markus
Date: 2008-11-21 11:59:03 -0500 (Fri, 21 Nov 2008)
New Revision: 7185
Modified:
core/trunk/src/test/java/org/jboss/cache/config/parsing/CacheConfigsTest.java
core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java
Log:
make code compilable and increse timeout
Modified: core/trunk/src/test/java/org/jboss/cache/config/parsing/CacheConfigsTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/config/parsing/CacheConfigsTest.java 2008-11-21 16:35:19 UTC (rev 7184)
+++ core/trunk/src/test/java/org/jboss/cache/config/parsing/CacheConfigsTest.java 2008-11-21 16:59:03 UTC (rev 7185)
@@ -51,7 +51,7 @@
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
CacheConfigsXmlParser ccxp = new CacheConfigsXmlParser();
- Map<String, Configuration> map = ccxp.parseConfigs(bais);
+ Map<String, Configuration> map = ccxp.parseConfigs(bais, null);
Map toExpect = buildExpectedValues();
assert map.equals(toExpect) : "Expected " + toExpect + " but was " + map;
@@ -87,7 +87,7 @@
ByteArrayInputStream bais = new ByteArrayInputStream(xml.getBytes());
CacheConfigsXmlParser ccxp = new CacheConfigsXmlParser();
- Map<String, Configuration> map = ccxp.parseConfigs(bais);
+ Map<String, Configuration> map = ccxp.parseConfigs(bais, null);
Map toExpect = buildExpectedValues();
assert map.equals(toExpect);
Modified: core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java 2008-11-21 16:35:19 UTC (rev 7184)
+++ core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java 2008-11-21 16:59:03 UTC (rev 7185)
@@ -66,7 +66,7 @@
Configuration c = new Configuration();
c.setClusterName("test");
- c.setStateRetrievalTimeout(1000);
+ c.setStateRetrievalTimeout(10000);
c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
c.setNodeLockingScheme(nodeLockingScheme);
c.setCacheMode(cacheMode);
16 years, 1 month
JBoss Cache SVN: r7184 - in core/trunk/src: main/java/org/jboss/cache/interceptors and 4 other directories.
by jbosscache-commits@lists.jboss.org
Author: mircea.markus
Date: 2008-11-21 11:35:19 -0500 (Fri, 21 Nov 2008)
New Revision: 7184
Modified:
core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
core/trunk/src/main/java/org/jboss/cache/interceptors/LegacyDataGravitatorInterceptor.java
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyGroupAssignmentTest.java
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationFailoverTest.java
core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationTestsBase.java
core/trunk/src/test/java/org/jboss/cache/loader/ClusteredCacheLoaderTest.java
core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java
core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/OptimisticReplicationListener.java
core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/PessReplicationListener.java
core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/ReplicationListener.java
Log:
test concurrency
Modified: core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/main/java/org/jboss/cache/RPCManagerImpl.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -120,7 +120,7 @@
private InterceptorChain interceptorChain;
private boolean isUsingBuddyReplication;
- private boolean isInLocalMode;
+ private volatile boolean isInLocalMode;
private ComponentRegistry componentRegistry;
private LockManager lockManager;
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/LegacyDataGravitatorInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/LegacyDataGravitatorInterceptor.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/LegacyDataGravitatorInterceptor.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -322,7 +322,7 @@
if (trace) log.trace("Requesting data gravitation for Fqn " + fqn);
List<Address> mbrs = rpcManager.getMembers();
- Boolean searchSubtrees = buddyManager.isDataGravitationSearchBackupTrees() ? Boolean.TRUE : Boolean.FALSE;
+ Boolean searchSubtrees = buddyManager.isDataGravitationSearchBackupTrees();
GravitateDataCommand command = commandsFactory.buildGravitateDataCommand(fqn, searchSubtrees);
// doing a GET_ALL is crappy but necessary since JGroups' GET_FIRST could return null results from nodes that do
// not have either the primary OR backup, and stop polling other valid nodes.
Modified: core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyGroupAssignmentTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyGroupAssignmentTest.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyGroupAssignmentTest.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -94,8 +94,8 @@
assertNoLocks(caches);
}
- public void testRemovalFromCluster2Buddies() throws Exception
- {
+ public void testRemovalFromCluster2Buddies() throws Throwable
+{
log.debug("Running testRemovalFromCluster2Buddies");
List<CacheSPI<Object, Object>> caches = createCaches(2, 4, false);
cachesTL.set(caches);
Modified: core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationFailoverTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationFailoverTest.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationFailoverTest.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -8,7 +8,9 @@
import org.jboss.cache.CacheSPI;
import org.jboss.cache.Fqn;
+import org.jboss.cache.commands.remote.DataGravitationCleanupCommand;
import org.jboss.cache.util.TestingUtil;
+import org.jboss.cache.util.internals.replicationlisteners.ReplicationListener;
import org.jgroups.JChannel;
import org.jgroups.protocols.DISCARD;
import static org.testng.AssertJUnit.*;
@@ -88,11 +90,13 @@
System.out.println("***** Killed original data owner, about to call a get on a different cache instance. *****");
+ ReplicationListener replListener = ReplicationListener.getReplicationListener(caches.get(1));
+ replListener.expect(DataGravitationCleanupCommand.class);
+
// according to data gravitation, a call to *any* cache should retrieve the data, and move the data to the new cache.
assertEquals("Value should have gravitated", value, caches.get(2).get(fqn, key));
+ replListener.waitForReplicationToOccur();
- delay(); // cleanup commands are async
-
TestingUtil.dumpCacheContents(caches);
// now lets test the eviction part of gravitation
@@ -173,9 +177,12 @@
System.out.println("*** Calling get() on cache[1] with force option");
+ ReplicationListener replicationListener0 = ReplicationListener.getReplicationListener(caches.get(0));
+ replicationListener0.expect(DataGravitationCleanupCommand.class);
+
caches.get(1).getInvocationContext().getOptionOverrides().setForceDataGravitation(true);
assertEquals("value", caches.get(1).get(fqn, key));
- delay(); // cleanup commands are async
+ replicationListener0.waitForReplicationToOccur(); // cleanup commands are async
TestingUtil.dumpCacheContents(caches);
@@ -218,8 +225,10 @@
assertNoLocks(caches);
// gravitate to 2:
+ ReplicationListener replListener1 = ReplicationListener.getReplicationListener(caches.get(0));
+ replListener1.expect(DataGravitationCleanupCommand.class);
caches.get(2).getNode(fqn); // expectWithTx entire subtree to gravitate.
- delay(); // cleanup commands are async
+ replListener1.waitForReplicationToOccur(); // cleanup commands are async
Fqn newBackupFqn = fqnTransformer.getBackupFqn(caches.get(2).getLocalAddress(), fqn);
Fqn newBackupFqn2 = fqnTransformer.getBackupFqn(caches.get(2).getLocalAddress(), fqn2);
@@ -248,9 +257,4 @@
assertNoLocks(caches);
}
-
- protected void delay()
- {
- TestingUtil.sleepThread(250);
- }
}
Modified: core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationTestsBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationTestsBase.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/buddyreplication/BuddyReplicationTestsBase.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -95,9 +95,9 @@
}
cachesTL.set(null);
System.gc();
-
+
new UnitTestCacheFactory().cleanUp();
-
+
}
protected final static int VIEW_BLOCK_TIMEOUT = 5000;
@@ -131,7 +131,7 @@
{
CacheSPI<Object, Object> c = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object, Object>().createCache(UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC, false, false, true), false);
- String threadId = Thread.currentThread().getName();
+ String threadId = Thread.currentThread().getName();
//c.getConfiguration().setClusterName("BuddyReplicationTest-" + threadId);
BuddyReplicationConfig brc = new BuddyReplicationConfig();
@@ -321,7 +321,7 @@
public void waitForBuddy(Cache dataOwner, Cache buddy, boolean onlyBuddy) throws Exception
{
- waitForBuddy(dataOwner, buddy, onlyBuddy, 60000);
+ waitForBuddy(dataOwner, buddy, onlyBuddy, 60000);
}
/**
@@ -333,7 +333,7 @@
long timeout = 60000 + caches.length;
for (int i = 0; i < caches.length - 1; i++)
{
- waitForBuddy(caches[i], caches[i+1], true, timeout);
+ waitForBuddy(caches[i], caches[i + 1], true, timeout);
}
waitForBuddy(caches[caches.length - 1], caches[0], true, timeout);
}
@@ -367,7 +367,7 @@
BuddyGroup group = buddyBuddyManager.buddyGroupsIParticipateIn.get(dataOwnerLocalAddress);
result = result & buddyBuddyManager.buddyGroupsIParticipateIn.containsKey(dataOwnerLocalAddress);
if (onlyBuddy) result = result && group.getBuddies().size() == 1;
- result = result & group!= null && group.getBuddies() != null && group.getBuddies().contains(buddyLocalAddress);
+ result = result & group != null && group.getBuddies() != null && group.getBuddies().contains(buddyLocalAddress);
return result;
}
Modified: core/trunk/src/test/java/org/jboss/cache/loader/ClusteredCacheLoaderTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/loader/ClusteredCacheLoaderTest.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/loader/ClusteredCacheLoaderTest.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -53,9 +53,7 @@
Configuration c1 = new Configuration();
Configuration c2 = new Configuration();
- //c1.setClusterName("CCL-Test-" + Thread.currentThread().getName());
c1.setStateRetrievalTimeout(2000);
- //c2.setClusterName("CCL-Test-" + Thread.currentThread().getName());
c2.setStateRetrievalTimeout(2000);
c1.setCacheMode(Configuration.CacheMode.REPL_SYNC);
c2.setCacheMode(Configuration.CacheMode.REPL_SYNC);
@@ -69,6 +67,8 @@
cache1 = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object, Object>().createCache(c1, false);
cache2 = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object, Object>().createCache(c2, false);
+ cache1.getConfiguration().setSerializationExecutorPoolSize(0);
+ cache2.getConfiguration().setSerializationExecutorPoolSize(0);
if (useRegionBasedMarshalling)
@@ -225,7 +225,7 @@
assertTrue("should exist", loader2.exists(fqn));
}
- public void testCacheLoaderThreadSafety() throws Exception
+ public void testCacheLoaderThreadSafety() throws Throwable
{
threadSafetyTest(true);
}
Modified: core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/options/cachemodelocal/CacheModeLocalTestBase.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -724,10 +724,8 @@
assertNull("should be invalidated", cache2.get(fqn, key));
}
- // now cache2
- replListener1.expect(PutDataMapCommand.class);
+ //do not expect replication for this one as the node is already thre
Node node2 = root2.addChild(fqn);
- replListener1.waitForReplicationToOccur();
mgr = cache2.getTransactionManager();
replListener1.expectWithTx(PutKeyValueCommand.class);
Modified: core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/OptimisticReplicationListener.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/OptimisticReplicationListener.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/OptimisticReplicationListener.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -27,10 +27,17 @@
*/
public void expect(Class<? extends ReplicableCommand>... expectedCommands)
{
- //in the case of optimistic replication, an prepare and an commit is expected foe each node
+ //in the case of optimistic replication, an prepare and an commit is expected foe each node
for (Class<? extends ReplicableCommand> command : expectedCommands)
{
- internalExpect(OptimisticPrepareCommand.class, CommitCommand.class);
+ if (isRemoteCommand(command))
+ {
+ internalExpect(command);
+ }
+ else
+ {
+ internalExpect(OptimisticPrepareCommand.class, CommitCommand.class);
+ }
}
}
@@ -42,7 +49,7 @@
internalExpect(OptimisticPrepareCommand.class, CommitCommand.class);
}
- protected void postCommandExecution(ReplicateCommand realOne)
+ protected void postReplicateExecution(ReplicateCommand realOne)
{
int initialExpectations = expectedCommands.size();
List<ReplicableCommand> mods = getAllModifications(realOne);
Modified: core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/PessReplicationListener.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/PessReplicationListener.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/PessReplicationListener.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -2,6 +2,7 @@
import org.jboss.cache.Cache;
import org.jboss.cache.commands.ReplicableCommand;
+import org.jboss.cache.commands.remote.DataGravitationCleanupCommand;
import org.jboss.cache.commands.tx.PrepareCommand;
import org.jboss.cache.commands.tx.CommitCommand;
import org.jboss.cache.commands.legacy.write.*;
@@ -29,6 +30,7 @@
mvcc2PessMap.put(PutKeyValueCommand.class, PessPutKeyValueCommand.class);
mvcc2PessMap.put(RemoveKeyCommand.class, PessRemoveKeyCommand.class);
mvcc2PessMap.put(RemoveNodeCommand.class, PessRemoveNodeCommand.class);
+ mvcc2PessMap.put(DataGravitationCleanupCommand.class, DataGravitationCleanupCommand.class);
}
@@ -66,6 +68,8 @@
private Class<? extends ReplicableCommand> getPessCommand(Class<? extends ReplicableCommand> command)
{
- return mvcc2PessMap.get((Class<? extends ReplicableCommand>) command);
+ Class<? extends ReplicableCommand> result = mvcc2PessMap.get((Class<? extends ReplicableCommand>) command);
+ if (result == null) throw new IllegalStateException("Unknown command: " + command);
+ return result;
}
}
Modified: core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/ReplicationListener.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/ReplicationListener.java 2008-11-21 16:28:39 UTC (rev 7183)
+++ core/trunk/src/test/java/org/jboss/cache/util/internals/replicationlisteners/ReplicationListener.java 2008-11-21 16:35:19 UTC (rev 7184)
@@ -3,7 +3,8 @@
import org.jboss.cache.*;
import org.jboss.cache.config.Configuration;
import org.jboss.cache.commands.ReplicableCommand;
-import org.jboss.cache.commands.remote.ReplicateCommand;
+import org.jboss.cache.commands.VisitableCommand;
+import org.jboss.cache.commands.remote.*;
import org.jboss.cache.commands.tx.PrepareCommand;
import org.jboss.cache.factories.ComponentRegistry;
import org.jboss.cache.io.ByteBuffer;
@@ -15,6 +16,7 @@
import org.jboss.cache.util.TestingUtil;
import org.jgroups.blocks.RpcDispatcher;
import org.jgroups.util.Buffer;
+import org.jgroups.Address;
import java.io.InputStream;
import java.io.ObjectInputStream;
@@ -61,6 +63,7 @@
private CountDownLatch latch = new CountDownLatch(1);
protected List<Class<? extends ReplicableCommand>> expectedCommands;
protected Configuration config;
+ protected final Address localAddress;
/**
* Builds a listener that will observe the given cache for recieving replication commands.
@@ -84,10 +87,12 @@
realDispatcher.setRequestMarshaller(delegate);
realDispatcher.setResponseMarshaller(delegate);
this.config = cache.getConfiguration();
+ this.localAddress = cache.getLocalAddress();
}
protected ReplicationListener()
{
+ localAddress = null;
}
abstract public void expect(Class<? extends ReplicableCommand>... expectedCommands);
@@ -138,44 +143,51 @@
public Object objectFromByteBuffer(byte bytes[]) throws Exception
{
Object result = marshaller.objectFromByteBuffer(bytes);
- if (result instanceof ReplicateCommand && expectedCommands != null)
- {
- ReplicateCommand replicateCommand = (ReplicateCommand) result;
- return new ReplicateCommandDelegate(replicateCommand);
- }
- return result;
+ return process(result);
}
- public Buffer objectToBuffer(Object o) throws Exception
+ public Object objectFromByteBuffer(byte[] bytes, int i, int i1) throws Exception
{
- return marshaller.objectToBuffer(o);
+ Object result = marshaller.objectFromByteBuffer(bytes, i, i1);
+ return process(result);
}
- public Object objectFromByteBuffer(byte[] bytes, int i, int i1) throws Exception
+ private Object process(Object result)
{
- Object result = marshaller.objectFromByteBuffer(bytes, i, i1);
- if (result instanceof ReplicateCommand && expectedCommands != null)
+ System.out.println(localAddress + " >>>> " + result );
+ boolean isReplicate = result instanceof ReplicateCommand;
+ boolean isRemote = result != null && isRemoteCommand(result.getClass());
+ if ((isReplicate || isRemote) && (expectedCommands != null))
{
- ReplicateCommand replicateCommand = (ReplicateCommand) result;
- return new ReplicateCommandDelegate(replicateCommand);
+ ReplicableCommand replicateCommand = (ReplicableCommand) result;
+ result = new ReplicableCommandDelegate(replicateCommand);
}
return result;
}
+
+ public Buffer objectToBuffer(Object o) throws Exception
+ {
+ return marshaller.objectToBuffer(o);
+ }
}
/**
* We want the notification to be performed only *after* the remote command is executed.
*/
- private class ReplicateCommandDelegate extends ReplicateCommand
+ private class ReplicableCommandDelegate implements ReplicableCommand
{
- ReplicateCommand realOne;
+ ReplicableCommand realOne;
- private ReplicateCommandDelegate(ReplicateCommand realOne)
+ private ReplicableCommandDelegate(ReplicableCommand realOne)
{
+ if (realOne instanceof VisitableCommand)
+ {
+ throw new IllegalArgumentException("Visitable commands not allowed!!! ;recieved="
+ + realOne.getClass().getName());
+ }
this.realOne = realOne;
}
- @Override
public Object perform(InvocationContext ctx) throws Throwable
{
try
@@ -184,19 +196,45 @@
}
finally
{
- postCommandExecution(realOne);
+ if (realOne instanceof ReplicateCommand)
+ {
+ postReplicateExecution((ReplicateCommand)realOne);
+ }
+ else
+ {
+ postNonVisitableExecution(realOne);
+ }
if (expectedCommands.isEmpty())
{
latch.countDown();
}
}
}
+
+ public int getCommandId()
+ {
+ return realOne.getCommandId();
+ }
+
+ public Object[] getParameters()
+ {
+ return realOne.getParameters();
+ }
+
+ public void setParameters(int commandId, Object[] parameters)
+ {
+ realOne.setParameters(commandId, parameters);
+ }
}
-
- protected void postCommandExecution(ReplicateCommand realOne)
+ protected void postNonVisitableExecution(ReplicableCommand realOne)
{
- System.out.println("Processed command: " + realOne + "; expecting - " + expectedCommands.size() + " commands");
+ expectedCommands.remove(realOne.getClass());
+ }
+
+ protected void postReplicateExecution(ReplicateCommand realOne)
+ {
+ System.out.println("Processed command: " + realOne + "; expecting " + expectedCommands.size() + " commands");
Iterator<Class<? extends ReplicableCommand>> it = expectedCommands.iterator();
while (it.hasNext())
{
@@ -254,7 +292,7 @@
if (result.command instanceof ReplicateCommand && expectedCommands != null)
{
ReplicateCommand replicateCommand = (ReplicateCommand) result.command;
- result.command = new ReplicateCommandDelegate(replicateCommand);
+ result.command = new ReplicableCommandDelegate(replicateCommand);
}
return result;
}
@@ -333,4 +371,11 @@
}
this.expectedCommands.addAll(Arrays.asList(expectedCommands));
}
+
+ protected boolean isRemoteCommand(Class clazz)
+ {
+ return clazz.equals(AnnounceBuddyPoolNameCommand.class) || clazz.equals(AssignToBuddyGroupCommand.class) ||
+ clazz.equals(ClusteredGetCommand.class) || clazz.equals(DataGravitationCleanupCommand.class) ||
+ clazz.equals(RemoveFromBuddyGroupCommand.class) || clazz.equals(ReplicateCommand.class);
+ }
}
16 years, 1 month
JBoss Cache SVN: r7183 - core/trunk/src/main/java/org/jboss/cache/buddyreplication.
by jbosscache-commits@lists.jboss.org
Author: mircea.markus
Date: 2008-11-21 11:28:39 -0500 (Fri, 21 Nov 2008)
New Revision: 7183
Modified:
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
Log:
fixed issue
Modified: core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java 2008-11-21 10:28:16 UTC (rev 7182)
+++ core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyManager.java 2008-11-21 16:28:39 UTC (rev 7183)
@@ -412,7 +412,9 @@
if (queue.peek() != STOP_NOTIFIER)
{
//first empty the queue. All queued up view changes that have not been processed yet are now obsolete.
- queue.clear();
+ /* Do not clear the queue here. It might happen that there is an new memebr added there, which must be
+ * notified about the pool membership.
+ */
if (trace) log.trace("Enqueueing " + mc + " for async processing");
queue.put(mc);
}
@@ -1151,15 +1153,6 @@
public void run()
{
log.trace("Started");
- // don't start this thread until the Buddy Manager has initialised as it cocks things up.
- try
- {
- initialisationLatch.await();
- }
- catch (InterruptedException e)
- {
- log.debug("Caught InterruptedException", e);
- }
while (!Thread.interrupted() && isRunning)
{
try
16 years, 1 month
JBoss Cache SVN: r7182 - searchable/trunk/src/main/java/org/jboss/cache/search.
by jbosscache-commits@lists.jboss.org
Author: navssurtani
Date: 2008-11-21 05:28:16 -0500 (Fri, 21 Nov 2008)
New Revision: 7182
Modified:
searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java
Log:
Committed updates to SCI so that everything compiles :)
Modified: searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java
===================================================================
--- searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java 2008-11-20 05:17:16 UTC (rev 7181)
+++ searchable/trunk/src/main/java/org/jboss/cache/search/SearchableCacheImpl.java 2008-11-21 10:28:16 UTC (rev 7182)
@@ -32,6 +32,7 @@
import org.jboss.cache.Node;
import org.jboss.cache.NodeNotExistsException;
import org.jboss.cache.Region;
+import org.jboss.cache.interceptors.base.CommandInterceptor;
import org.jboss.cache.config.Configuration;
import org.jgroups.Address;
@@ -422,4 +423,24 @@
{
cache.endBatch(successful);
}
+
+ public void removeInterceptor(Class<? extends CommandInterceptor> interceptorType)
+ {
+ cache.removeInterceptor(interceptorType);
+ }
+
+ public void removeInterceptor(int position)
+ {
+ cache.removeInterceptor(position);
+ }
+
+ public void addInterceptor(CommandInterceptor i, Class<? extends CommandInterceptor> afterInterceptor)
+ {
+ cache.addInterceptor(i, afterInterceptor);
+ }
+
+ public void addInterceptor(CommandInterceptor i, int position)
+ {
+ cache.addInterceptor(i, position);
+ }
}
16 years, 1 month
JBoss Cache SVN: r7181 - in core/branches/flat/src: main/java/org/jboss/starobrno/interceptors and 3 other directories.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2008-11-20 00:17:16 -0500 (Thu, 20 Nov 2008)
New Revision: 7181
Added:
core/branches/flat/src/test/java/org/jboss/starobrno/loader/
core/branches/flat/src/test/java/org/jboss/starobrno/loader/CacheLoaderTest.java
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java
core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java
core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java
Log:
Implement getMarshaller()
Add a cache loader test
Fix type-o
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java 2008-11-20 04:56:54 UTC (rev 7180)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java 2008-11-20 05:17:16 UTC (rev 7181)
@@ -21,12 +21,18 @@
*/
package org.jboss.starobrno;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
import org.jboss.cache.CacheStatus;
import org.jboss.cache.Version;
import org.jboss.cache.buddyreplication.BuddyManager;
import org.jboss.cache.buddyreplication.GravitateResult;
-import org.jboss.cache.loader.CacheLoaderManager;
-import org.jboss.cache.marshall.Marshaller;
import org.jboss.starobrno.atomic.AtomicHashMap;
import org.jboss.starobrno.atomic.AtomicMap;
import org.jboss.starobrno.atomic.AtomicMapCache;
@@ -50,20 +56,15 @@
import org.jboss.starobrno.interceptors.InterceptorChain;
import org.jboss.starobrno.interceptors.base.CommandInterceptor;
import org.jboss.starobrno.invocation.InvocationContextContainer;
+import org.jboss.starobrno.loader.CacheLoaderManager;
import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.marshall.ExtendedMarshaller;
import org.jboss.starobrno.notifications.Notifier;
import org.jboss.starobrno.statetransfer.StateTransferManager;
import org.jboss.starobrno.transaction.GlobalTransaction;
import org.jboss.starobrno.transaction.TransactionTable;
import org.jgroups.Address;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
/**
* @author Mircea.Markus(a)jboss.com
*/
@@ -79,6 +80,7 @@
protected ComponentRegistry componentRegistry;
protected TransactionManager transactionManager;
protected RPCManager rpcManager;
+ protected ExtendedMarshaller marshaller;
private String name;
private EvictionManager evictionManager;
private DataContainer dataContainer;
@@ -96,6 +98,7 @@
TransactionManager transactionManager,
BatchContainer batchContainer,
RPCManager rpcManager, DataContainer dataContainer,
+ ExtendedMarshaller marshaller,
LockManager lockManager)
{
this.invocationContextContainer = invocationContextContainer;
@@ -109,6 +112,7 @@
this.rpcManager = rpcManager;
this.evictionManager = evictionManager;
this.dataContainer = dataContainer;
+ this.marshaller = marshaller;
this.lockManager = lockManager;
}
@@ -274,9 +278,9 @@
throw new IllegalStateException();//todo Implement me properly
}
- public Marshaller getMarshaller()
+ public ExtendedMarshaller getMarshaller()
{
- throw new IllegalStateException();//todo Implement me properly
+ return marshaller;
}
public void addInterceptor(CommandInterceptor i, int position)
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java 2008-11-20 04:56:54 UTC (rev 7180)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java 2008-11-20 05:17:16 UTC (rev 7181)
@@ -21,27 +21,30 @@
*/
package org.jboss.starobrno;
+import java.util.List;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
import net.jcip.annotations.ThreadSafe;
+
import org.jboss.cache.Node;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.buddyreplication.BuddyManager;
import org.jboss.cache.buddyreplication.GravitateResult;
-import org.jboss.cache.loader.CacheLoaderManager;
import org.jboss.cache.marshall.Marshaller;
import org.jboss.starobrno.context.InvocationContext;
import org.jboss.starobrno.factories.ComponentRegistry;
import org.jboss.starobrno.interceptors.base.CommandInterceptor;
import org.jboss.starobrno.loader.CacheLoader;
+import org.jboss.starobrno.loader.CacheLoaderManager;
import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.marshall.ExtendedMarshaller;
import org.jboss.starobrno.notifications.Notifier;
import org.jboss.starobrno.statetransfer.StateTransferManager;
import org.jboss.starobrno.transaction.GlobalTransaction;
import org.jboss.starobrno.transaction.TransactionTable;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.List;
-
/**
* A more detailed interface to {@link Cache}, which is used when writing plugins for or extending JBoss Cache. A reference
* to this interface should only be obtained when it is passed in to your code, for example when you write an
@@ -98,7 +101,7 @@
*
* @return an instance of {@link Marshaller}
*/
- Marshaller getMarshaller();
+ ExtendedMarshaller getMarshaller();
/**
* Retrieves the current CacheCacheLoaderManager instance associated with the current Cache instance.
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java 2008-11-20 04:56:54 UTC (rev 7180)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java 2008-11-20 05:17:16 UTC (rev 7181)
@@ -147,7 +147,7 @@
}
// Reuse the lock and create a new entry for loading
- MVCCEntry n = creator.wrapEntryForWriting(ctx, key, false, true);
+ MVCCEntry n = creator.wrapEntryForWriting(ctx, key, true, false);
n = loadEntry(ctx, key, n);
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java 2008-11-20 04:56:54 UTC (rev 7180)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java 2008-11-20 05:17:16 UTC (rev 7181)
@@ -31,12 +31,12 @@
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.RegionManager;
import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
-import org.jboss.cache.marshall.Marshaller;
import org.jboss.starobrno.CacheException;
import org.jboss.starobrno.CacheSPI;
import org.jboss.starobrno.marshall.EntryData;
import org.jboss.starobrno.marshall.EntryDataExceptionMarker;
import org.jboss.starobrno.marshall.EntryDataMarker;
+import org.jboss.starobrno.marshall.ExtendedMarshaller;
/**
* A convenience abstract implementation of a {@link CacheLoader}. Specific methods to note are methods like
@@ -138,7 +138,7 @@
}
}
- protected Marshaller getMarshaller()
+ protected ExtendedMarshaller getMarshaller()
{
return cache.getMarshaller();
}
Added: core/branches/flat/src/test/java/org/jboss/starobrno/loader/CacheLoaderTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/loader/CacheLoaderTest.java (rev 0)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/loader/CacheLoaderTest.java 2008-11-20 05:17:16 UTC (rev 7181)
@@ -0,0 +1,86 @@
+package org.jboss.starobrno.loader;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import java.io.File;
+import java.util.Properties;
+
+import org.jboss.cache.CacheFactory;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.UnitTestCacheFactory;
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+import org.jboss.starobrno.util.TestingUtil;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests CacheLoader
+ *
+ * @author Jason T. Greene
+ */
+
+@Test(groups = {"functional", "pessimistic"})
+public class CacheLoaderTest
+{
+ private ThreadLocal<CacheSPI<String, String>> cacheTL = new ThreadLocal<CacheSPI<String, String>>();
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+
+ try
+ {
+ File dir = new File("file-loader-dir");
+ for (File file : dir.listFiles())
+ file.delete();
+ }
+ catch (Throwable t)
+ {
+ }
+
+
+ // start a single cache instance
+ CacheFactory<String, String> cf = new UnitTestCacheFactory<String, String>();
+ CacheSPI<String, String> cache = (CacheSPI<String, String>) cf.createCache("configs/local-tx.xml", false);
+ cache.getConfiguration().setEvictionConfig(null);
+ CacheLoaderConfig loaderConfig = new CacheLoaderConfig();
+ IndividualCacheLoaderConfig fileConfig = new IndividualCacheLoaderConfig();
+ fileConfig.setClassName("org.jboss.starobrno.loader.FileCacheLoader");
+ Properties p = new Properties();
+ p.setProperty("location", "file-loader-dir");
+ fileConfig.setProperties(p);
+ loaderConfig.addIndividualCacheLoaderConfig(fileConfig);
+ cache.getConfiguration().setCacheLoaderConfig(loaderConfig);
+ configure(cache.getConfiguration());
+ cache.start();
+ cacheTL.set(cache);
+
+ }
+
+ protected void configure(Configuration c)
+ {
+ }
+
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ CacheSPI<String, String> cache = cacheTL.get();
+ TestingUtil.killCaches(cache);
+ cacheTL.set(null);
+ }
+
+ public void testLoader()
+ {
+ CacheSPI<String, String> cache = cacheTL.get();
+ cache.put("foo", "foo-data");
+ cache.put("foo2", "foo2-data");
+ cache.evict("foo");
+ cache.evict("foo2");
+ assertEquals("foo-data", cache.get("foo"));
+ assertEquals("foo2-data", cache.get("foo2"));
+ }
+}
Property changes on: core/branches/flat/src/test/java/org/jboss/starobrno/loader/CacheLoaderTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
16 years, 1 month
JBoss Cache SVN: r7180 - in core/branches/flat/src: main/java/org/jboss/starobrno/factories and 4 other directories.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2008-11-19 23:56:54 -0500 (Wed, 19 Nov 2008)
New Revision: 7180
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java
core/branches/flat/src/main/java/org/jboss/starobrno/factories/EmptyConstructorFactory.java
core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java
Log:
More cache loader fixes
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java 2008-11-20 04:09:47 UTC (rev 7179)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/parsing/XmlConfigurationParser.java 2008-11-20 04:56:54 UTC (rev 7180)
@@ -291,7 +291,7 @@
{
if (element == null) return; //no eviction might be configured
EvictionElementParser evictionElementParser = new EvictionElementParser();
- config.setEvictionConfig(evictionElementParser.parseEvictionElement(element));
+ //config.setEvictionConfig(evictionElementParser.parseEvictionElement(element));
}
private void configureJmxStatistics(Element element)
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/factories/EmptyConstructorFactory.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/factories/EmptyConstructorFactory.java 2008-11-20 04:09:47 UTC (rev 7179)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/factories/EmptyConstructorFactory.java 2008-11-20 04:56:54 UTC (rev 7180)
@@ -22,6 +22,11 @@
package org.jboss.starobrno.factories;
+import org.jboss.cache.RegionRegistry;
+import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
+import org.jboss.cache.invocation.CacheInvocationDelegate;
+import org.jboss.cache.lock.LockStrategyFactory;
+import org.jboss.starobrno.RPCManager;
import org.jboss.starobrno.batch.BatchContainer;
import org.jboss.starobrno.commands.CommandsFactory;
import org.jboss.starobrno.config.ConfigurationException;
@@ -29,19 +34,13 @@
import org.jboss.starobrno.factories.annotations.DefaultFactoryFor;
import org.jboss.starobrno.factories.context.ContextFactory;
import org.jboss.starobrno.invocation.InvocationContextContainer;
-import org.jboss.starobrno.notifications.Notifier;
-import org.jboss.starobrno.transaction.TransactionTable;
-import org.jboss.starobrno.remoting.RPCManagerImpl;
-import org.jboss.starobrno.remoting.ChannelMessageListener;
+import org.jboss.starobrno.loader.CacheLoaderManager;
import org.jboss.starobrno.marshall.ExtendedMarshaller;
-import org.jboss.starobrno.marshall.CacheMarshallerStarobrno;
import org.jboss.starobrno.marshall.VersionAwareMarshaller;
-import org.jboss.starobrno.RPCManager;
-import org.jboss.cache.loader.CacheLoaderManager;
-import org.jboss.cache.invocation.CacheInvocationDelegate;
-import org.jboss.cache.lock.LockStrategyFactory;
-import org.jboss.cache.buddyreplication.BuddyFqnTransformer;
-import org.jboss.cache.RegionRegistry;
+import org.jboss.starobrno.notifications.Notifier;
+import org.jboss.starobrno.remoting.ChannelMessageListener;
+import org.jboss.starobrno.remoting.RPCManagerImpl;
+import org.jboss.starobrno.transaction.TransactionTable;
/**
* Simple factory that just uses reflection and an empty constructor of the component type.
@@ -68,7 +67,7 @@
{
componentImpl = VersionAwareMarshaller.class;
}
- else
+ else
if (componentType.equals(RPCManager.class))
{
componentImpl = RPCManagerImpl.class;
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java 2008-11-20 04:09:47 UTC (rev 7179)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java 2008-11-20 04:56:54 UTC (rev 7180)
@@ -24,7 +24,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.jboss.cache.transaction.TransactionTable;
import org.jboss.starobrno.commands.read.GetKeyValueCommand;
import org.jboss.starobrno.commands.write.PutKeyValueCommand;
import org.jboss.starobrno.commands.write.RemoveCommand;
@@ -42,6 +41,7 @@
import org.jboss.starobrno.loader.CacheLoader;
import org.jboss.starobrno.loader.CacheLoaderManager;
import org.jboss.starobrno.notifications.Notifier;
+import org.jboss.starobrno.transaction.TransactionTable;
/**
* Loads nodes that don't exist at the time of the call into memory from the CacheLoader
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java 2008-11-20 04:09:47 UTC (rev 7179)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java 2008-11-20 04:56:54 UTC (rev 7180)
@@ -91,7 +91,7 @@
{
// TODO: Inject CacheSPI once we have the cache loaders not relying on a tree structure
this.config = configuration.getCacheLoaderConfig();
-// this.cache = cache;
+ this.cache = cache;
this.configuration = configuration;
this.registry = registry;
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java 2008-11-20 04:09:47 UTC (rev 7179)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java 2008-11-20 04:56:54 UTC (rev 7180)
@@ -6,7 +6,7 @@
import org.testng.annotations.Test;
/**
- * MVCC version of {@link org.jboss.cache.api.CacheAPITest}
+ * MVCC version of {@link org.jboss.cache.api.CacheLoaderTest}
*/
@Test(groups = {"functional", "mvcc"})
public class CacheAPIMVCCTest extends CacheAPITest
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java 2008-11-20 04:09:47 UTC (rev 7179)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java 2008-11-20 04:56:54 UTC (rev 7180)
@@ -6,7 +6,7 @@
import org.testng.annotations.Test;
/**
- * MVCC version of {@link org.jboss.cache.api.CacheAPITest}
+ * MVCC version of {@link org.jboss.cache.api.CacheLoaderTest}
*/
@Test(groups = {"functional", "mvcc"})
public class CacheAPIMVCCTest extends CacheAPITest
16 years, 1 month
JBoss Cache SVN: r7178 - in core/branches/flat/src: main/java/org/jboss/starobrno/config and 6 other directories.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2008-11-19 23:06:04 -0500 (Wed, 19 Nov 2008)
New Revision: 7178
Added:
core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheStoreInterceptor.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractDelegatingCacheLoader.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoader.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoaderConfig.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/ChainingCacheLoader.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/ReadOnlyDelegatingCacheLoader.java
Removed:
core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/base/SkipCheckChainedInterceptor.java
Modified:
core/branches/flat/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java
core/branches/flat/src/main/java/org/jboss/starobrno/config/CacheLoaderConfig.java
core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java
core/branches/flat/src/main/java/org/jboss/starobrno/factories/InterceptorChainFactory.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoader.java
core/branches/flat/src/main/java/org/jboss/starobrno/loader/FileCacheLoader.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java
Log:
More cacheloader work
Modified: core/branches/flat/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/cache/loader/CacheLoaderManager.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -21,28 +21,28 @@
*/
package org.jboss.cache.loader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheSPI_Legacy;
import org.jboss.cache.Fqn;
import org.jboss.cache.RegionManager;
-import org.jboss.starobrno.util.ReflectionUtil;
import org.jboss.starobrno.CacheException;
import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.ConfigurationException;
import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig;
-import org.jboss.starobrno.config.Configuration;
-import org.jboss.starobrno.config.ConfigurationException;
import org.jboss.starobrno.factories.ComponentRegistry;
import org.jboss.starobrno.factories.annotations.Inject;
import org.jboss.starobrno.factories.annotations.Start;
import org.jboss.starobrno.factories.annotations.Stop;
+import org.jboss.starobrno.util.ReflectionUtil;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Set;
-import java.util.StringTokenizer;
-
/**
* Manages all cache loader functionality. This class is typically initialised with an XML DOM Element,
* represeting a cache loader configuration, or a {@link org.jboss.cache.config.CacheLoaderConfig} object.
@@ -225,7 +225,7 @@
private CacheLoader createCacheLoader(CacheLoaderConfig.IndividualCacheLoaderConfig cfg, CacheSPI_Legacy cache) throws Exception
{
// create loader
- CacheLoader tmpLoader = cfg.getCacheLoader() == null ? createInstance(cfg.getClassName()) : cfg.getCacheLoader();
+ CacheLoader tmpLoader = (CacheLoader)(cfg.getCacheLoader() == null ? createInstance(cfg.getClassName()) : cfg.getCacheLoader());
if (tmpLoader != null)
{
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/config/CacheLoaderConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/config/CacheLoaderConfig.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/config/CacheLoaderConfig.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -21,14 +21,14 @@
*/
package org.jboss.starobrno.config;
-import org.jboss.cache.loader.CacheLoader;
-import org.jboss.cache.loader.SingletonStoreCacheLoader;
-import org.jboss.starobrno.util.Util;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
+import org.jboss.cache.loader.SingletonStoreCacheLoader;
+import org.jboss.starobrno.loader.CacheLoader;
+import org.jboss.starobrno.util.Util;
+
/**
* Holds the configuration of the cache loader chain. ALL cache loaders should be defined using this class, adding
* individual cache loaders to the chain by calling {@link CacheLoaderConfig#addIndividualCacheLoaderConfig}
@@ -193,7 +193,7 @@
private boolean purgeOnStartup;
private SingletonStoreConfig singletonStoreConfig;
- private transient CacheLoader cacheLoader;
+ private transient CacheLoader<Object, Object> cacheLoader;
protected void populateFromBaseConfig(IndividualCacheLoaderConfig base)
{
@@ -271,7 +271,7 @@
* @return cache loader, if one exists
* @since 2.1.0
*/
- public CacheLoader getCacheLoader()
+ public CacheLoader<Object,Object> getCacheLoader()
{
return cacheLoader;
}
@@ -283,7 +283,7 @@
* @param cacheLoader cacheLoader to set
* @since 2.1.0
*/
- public void setCacheLoader(CacheLoader cacheLoader)
+ public void setCacheLoader(CacheLoader<Object,Object> cacheLoader)
{
this.cacheLoader = cacheLoader;
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/container/MVCCEntryCreator.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -167,7 +167,7 @@
* @throws org.jboss.starobrno.lock.TimeoutException
* if we are unable to acquire the lock after a specified timeout.
*/
- private boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException
+ public boolean acquireLock(InvocationContext ctx, Object key) throws InterruptedException, TimeoutException
{
// don't EVER use lockManager.isLocked() since with lock striping it may be the case that we hold the relevant
// lock which may be shared with another Fqn that we have a lock for already.
@@ -184,4 +184,9 @@
}
return false;
}
+
+ public void releaseLock(InvocationContext ctx, Object key)
+ {
+ lockManager.unlock(key, lockManager.getOwner(key));
+ }
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/factories/InterceptorChainFactory.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/factories/InterceptorChainFactory.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/factories/InterceptorChainFactory.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -124,22 +124,22 @@
}
// TODO: Uncomment once the CacheLoader has been moved to Starobrno
-// if (configuration.isUsingCacheLoaders())
-// {
+ if (configuration.isUsingCacheLoaders())
+ {
// if (configuration.getCacheLoaderConfig().isPassivation())
// {
// interceptorChain.appendIntereceptor(createInterceptor(ActivationInterceptor.class));
// }
// else
-// {
-// interceptorChain.appendIntereceptor(createInterceptor(CacheLoaderInterceptor.class));
-// }
-// }
+ {
+ interceptorChain.appendIntereceptor(createInterceptor(CacheLoaderInterceptor.class));
+ }
+ }
interceptorChain.appendIntereceptor(createInterceptor(LockingInterceptor.class));
// TODO: Uncomment once the CacheLoader has been moved to Starobrno
-// if (configuration.isUsingCacheLoaders())
-// {
+ if (configuration.isUsingCacheLoaders())
+ {
// if (configuration.getCacheLoaderConfig().isPassivation())
// {
//
@@ -147,13 +147,13 @@
//
// }
// else
-// {
+ {
+
+ interceptorChain.appendIntereceptor(createInterceptor(CacheStoreInterceptor.class));
+
+ }
+ }
//
-// interceptorChain.appendIntereceptor(createInterceptor(CacheStoreInterceptor.class));
-//
-// }
-// }
-//
// if (configuration.isUsingBuddyReplication())
// {
//
Added: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,228 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.interceptors;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.cache.transaction.TransactionTable;
+import org.jboss.starobrno.commands.read.GetKeyValueCommand;
+import org.jboss.starobrno.commands.write.PutKeyValueCommand;
+import org.jboss.starobrno.commands.write.RemoveCommand;
+import org.jboss.starobrno.commands.write.ReplaceCommand;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.container.DataContainer;
+import org.jboss.starobrno.container.MVCCEntry;
+import org.jboss.starobrno.container.MVCCEntryCreator;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.factories.annotations.Start;
+import org.jboss.starobrno.interceptors.base.JmxStatsCommandInterceptor;
+import org.jboss.starobrno.jmx.annotations.ManagedAttribute;
+import org.jboss.starobrno.jmx.annotations.ManagedOperation;
+import org.jboss.starobrno.loader.CacheLoader;
+import org.jboss.starobrno.loader.CacheLoaderManager;
+import org.jboss.starobrno.notifications.Notifier;
+
+/**
+ * Loads nodes that don't exist at the time of the call into memory from the CacheLoader
+ *
+ * @author Bela Ban
+ * @version $Id$
+ */
+public class CacheLoaderInterceptor extends JmxStatsCommandInterceptor
+{
+ private long cacheLoads = 0;
+ private long cacheMisses = 0;
+ private CacheLoaderManager clm;
+
+ protected TransactionTable txTable = null;
+ protected CacheLoader<Object, Object> loader;
+ protected DataContainer<Object, Object> dataContainer;
+ protected Notifier notifier;
+ protected MVCCEntryCreator creator;
+
+ protected boolean isActivation = false;
+// protected boolean usingVersionedInvalidation = false;
+
+
+ /**
+ * True if CacheStoreInterceptor is in place.
+ * This allows us to skip loading keys for remove(Fqn, key) and put(Fqn, key).
+ * It also affects removal of node data and listing children.
+ */
+ protected boolean useCacheStore = true;
+
+ @Inject
+ protected void injectDependencies(TransactionTable txTable, CacheLoaderManager clm, Configuration configuration,
+ DataContainer<Object, Object> dataContainer, MVCCEntryCreator creator, Notifier notifier)
+ {
+ this.txTable = txTable;
+ this.clm = clm;
+// CacheMode mode = configuration.getCacheMode();
+// usingVersionedInvalidation = mode.isInvalidation();
+ this.dataContainer = dataContainer;
+ this.notifier = notifier;
+ this.creator = creator;
+ }
+
+ @Start
+ protected void startInterceptor()
+ {
+ loader = clm.getCacheLoader();
+ }
+
+ @Override
+ public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable
+ {
+ if (command.getKey() != null)
+ {
+ loadIfNeeded(ctx, command.getKey());
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+
+ @Override
+ public Object visitGetKeyValueCommand(InvocationContext ctx, GetKeyValueCommand command) throws Throwable
+ {
+ if (command.getKey() != null)
+ {
+ loadIfNeeded(ctx, command.getKey());
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable
+ {
+ if (command.getKey() != null)
+ {
+ loadIfNeeded(ctx, command.getKey());
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command) throws Throwable
+ {
+ if (command.getKey() != null)
+ {
+ loadIfNeeded(ctx, command.getKey());
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ private void loadIfNeeded(InvocationContext ctx, Object key) throws Throwable
+ {
+ if (dataContainer.containsKey(key) || !loader.exists(key))
+ return;
+
+ // Obtain a temporary lock to verify the key is not being concurrently added
+ boolean release = creator.acquireLock(ctx, key);
+ if (dataContainer.containsKey(key))
+ {
+ if (release)
+ creator.releaseLock(ctx, key);
+ return;
+ }
+
+ // Reuse the lock and create a new entry for loading
+ MVCCEntry n = creator.wrapEntryForWriting(ctx, key, false, true);
+ n = loadEntry(ctx, key, n);
+ }
+
+ /**
+ * Loads a node from disk; if it exists creates parent TreeNodes.
+ * If it doesn't exist on disk but in memory, clears the
+ * uninitialized flag, otherwise returns null.
+ */
+ private MVCCEntry loadEntry(InvocationContext ctx, Object key, MVCCEntry entry) throws Exception
+ {
+ if (trace) log.trace("loading entry " + key + " entry is " + entry);
+
+ Object value = loader.get(key);
+ boolean nodeExists = (value != null);
+ if (trace) log.trace("nodeExists " + nodeExists);
+
+ if (getStatisticsEnabled())
+ {
+ if (nodeExists)
+ {
+ cacheLoads++;
+ }
+ else
+ {
+ cacheMisses++;
+ }
+ }
+
+ if (value != null)
+ {
+ if (trace) log.trace("Entry is not null, loading");
+// notifier.notifyNodeLoaded(fqn, true, Collections.emptyMap(), ctx);
+// if (isActivation)
+// {
+// notifier.notifyNodeActivated(fqn, true, Collections.emptyMap(), ctx);
+// }
+
+ entry.setValue(value);
+ entry.setValid(true);
+
+// notifier.notifyNodeLoaded(fqn, false, nodeData, ctx);
+// if (isActivation)
+// {
+// notifier.notifyNodeActivated(fqn, false, nodeData, ctx);
+// }
+ }
+
+ return entry;
+ }
+
+ @ManagedAttribute(description = "number of cache loader node loads")
+ public long getCacheLoaderLoads()
+ {
+ return cacheLoads;
+ }
+
+ @ManagedAttribute(description = "number of cache loader node misses")
+ public long getCacheLoaderMisses()
+ {
+ return cacheMisses;
+ }
+
+ @ManagedOperation
+ public void resetStatistics()
+ {
+ cacheLoads = 0;
+ cacheMisses = 0;
+ }
+
+ @ManagedOperation
+ public Map<String, Object> dumpStatistics()
+ {
+ Map<String, Object> retval = new HashMap<String, Object>();
+ retval.put("CacheLoaderLoads", cacheLoads);
+ retval.put("CacheLoaderMisses", cacheMisses);
+ return retval;
+ }
+}
\ No newline at end of file
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheLoaderInterceptor.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheStoreInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheStoreInterceptor.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheStoreInterceptor.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,363 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.interceptors;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.jmx.annotations.ManagedAttribute;
+import org.jboss.cache.jmx.annotations.ManagedOperation;
+import org.jboss.starobrno.commands.AbstractVisitor;
+import org.jboss.starobrno.commands.VisitableCommand;
+import org.jboss.starobrno.commands.tx.CommitCommand;
+import org.jboss.starobrno.commands.tx.PrepareCommand;
+import org.jboss.starobrno.commands.tx.RollbackCommand;
+import org.jboss.starobrno.commands.write.ClearCommand;
+import org.jboss.starobrno.commands.write.PutKeyValueCommand;
+import org.jboss.starobrno.commands.write.PutMapCommand;
+import org.jboss.starobrno.commands.write.RemoveCommand;
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.context.InvocationContext;
+import org.jboss.starobrno.context.TransactionContext;
+import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.factories.annotations.Start;
+import org.jboss.starobrno.interceptors.base.JmxStatsCommandInterceptor;
+import org.jboss.starobrno.loader.CacheLoader;
+import org.jboss.starobrno.loader.CacheLoaderManager;
+import org.jboss.starobrno.loader.Modification;
+import org.jboss.starobrno.loader.Modification.ModificationType;
+import org.jboss.starobrno.transaction.GlobalTransaction;
+
+/**
+ * Writes modifications back to the store on the way out: stores modifications back
+ * through the CacheLoader, either after each method call (no TXs), or at TX commit.
+ *
+ * @author Bela Ban
+ * @version $Id$
+ */
+public class CacheStoreInterceptor extends JmxStatsCommandInterceptor
+{
+ private CacheLoaderConfig loaderConfig = null;
+ private TransactionManager txMgr = null;
+ private HashMap<GlobalTransaction, Integer> txStores = new HashMap<GlobalTransaction, Integer>();
+ private Map<GlobalTransaction, Set<Object>> preparingTxs = new ConcurrentHashMap<GlobalTransaction, Set<Object>>();
+ private long cacheStores = 0;
+ CacheLoader<Object, Object> loader;
+ private CacheLoaderManager loaderManager;
+ private boolean statsEnabled;
+
+ public CacheStoreInterceptor()
+ {
+ log = LogFactory.getLog(getClass());
+ trace = log.isTraceEnabled();
+ }
+
+ @Inject
+ protected void init(CacheLoaderManager loaderManager, TransactionManager txManager, CacheLoaderConfig clConfig)
+ {
+ // never inject a CacheLoader at this stage - only a CacheLoaderManager, since the CacheLoaderManager only creates a CacheLoader instance when it @Starts.
+ this.loaderManager = loaderManager;
+ this.loaderConfig = clConfig;
+ txMgr = txManager;
+ }
+
+ @Start
+ protected void start()
+ {
+ // this should only happen after the CacheLoaderManager has started, since the CacheLoaderManager only creates the CacheLoader instance in its @Start method.
+ loader = loaderManager.getCacheLoader();
+ this.setStatisticsEnabled(configuration.getExposeManagementStatistics());
+ }
+
+ /**
+ * if this is a shared cache loader and the call is of remote origin, pass up the chain
+ */
+ public final boolean skip(InvocationContext ctx, VisitableCommand command)
+ {
+ if ((!ctx.isOriginLocal() && loaderConfig.isShared()) || ctx.getOptionOverrides().isSuppressPersistence())
+ {
+ if (trace)
+ log.trace("Passing up method call and bypassing this interceptor since the cache loader is shared and this call originated remotely.");
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Object visitCommitCommand(InvocationContext ctx, CommitCommand command) throws Throwable
+ {
+ if (!skip(ctx, command) && inTransaction())
+ {
+ if (ctx.getTransactionContext().hasAnyModifications())
+ {
+ // this is a commit call.
+ GlobalTransaction gtx = command.getGlobalTransaction();
+ if (trace) log.trace("Calling loader.commit() for gtx " + gtx);
+ // sync call (a write) on the loader
+ // ignore modified FQNs
+ // List fqnsModified = getFqnsFromModificationList(txTable.get(globalTransaction).getCacheLoaderModifications());
+ try
+ {
+ loader.commit(gtx);
+ }
+ catch (Throwable t)
+ {
+ preparingTxs.remove(gtx);
+ throw t;
+ }
+ if (getStatisticsEnabled())
+ {
+ Integer puts = (Integer) txStores.get(gtx);
+ if (puts != null)
+ {
+ cacheStores = cacheStores + puts;
+ }
+ txStores.remove(gtx);
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+ else
+ {
+ if (trace) log.trace("Commit called with no modifications; ignoring.");
+ }
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object visitRollbackCommand(InvocationContext ctx, RollbackCommand command) throws Throwable
+ {
+ if (!skip(ctx, command) && inTransaction())
+ {
+ if (trace) log.trace("transactional so don't put stuff in the cloader yet.");
+ if (ctx.getTransactionContext().hasAnyModifications())
+ {
+ GlobalTransaction gtx = command.getGlobalTransaction();
+ // this is a rollback method
+ if (preparingTxs.containsKey(gtx))
+ {
+ preparingTxs.remove(gtx);
+ loader.rollback(gtx);
+ }
+ if (getStatisticsEnabled()) txStores.remove(gtx);
+ }
+ else
+ {
+ if (trace) log.trace("Rollback called with no modifications; ignoring.");
+ }
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object visitPrepareCommand(InvocationContext ctx, PrepareCommand command) throws Throwable
+ {
+ if (!skip(ctx, command) && inTransaction())
+ {
+ if (trace) log.trace("transactional so don't put stuff in the cloader yet.");
+ prepareCacheLoader(command.getGlobalTransaction(), ctx.getTransactionContext(), command.isOnePhaseCommit());
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable
+ {
+ if (!skip(ctx, command) && !inTransaction())
+ {
+ Object returnValue = loader.remove(command.getKey());
+ invokeNextInterceptor(ctx, command);
+ return returnValue;
+ }
+ return invokeNextInterceptor(ctx, command);
+ }
+
+ @Override
+ public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable
+ {
+ Object returnValue = invokeNextInterceptor(ctx, command);
+ if (skip(ctx, command) || inTransaction())
+ return returnValue;
+
+ returnValue = loader.put(command.getKey(), command.getValue());
+ if (getStatisticsEnabled()) cacheStores++;
+
+ return returnValue;
+ }
+
+ @Override
+ public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable
+ {
+ Object returnValue = invokeNextInterceptor(ctx, command);
+ if (skip(ctx, command) || inTransaction())
+ return returnValue;
+
+ // Perhaps this should be optimized
+ Map<Object, Object> map = command.getMap();
+ List<Modification> modifications = toModifications(map);
+ loader.put(modifications);
+
+ if (getStatisticsEnabled()) cacheStores++;
+
+ return returnValue;
+ }
+
+ private static List<Modification> toModifications(Map<Object, Object> map)
+ {
+ List<Modification> modifications = new ArrayList<Modification>(map.size());
+ for (Map.Entry<Object, Object> entry : map.entrySet())
+ modifications.add(new Modification(ModificationType.PUT, entry.getKey(), entry.getValue()));
+ return modifications;
+ }
+
+ private boolean inTransaction() throws SystemException
+ {
+ return txMgr != null && txMgr.getTransaction() != null;
+ }
+
+ private void prepareCacheLoader(GlobalTransaction gtx, TransactionContext transactionContext, boolean onePhase) throws Throwable
+ {
+ if (transactionContext == null)
+ {
+ throw new Exception("transactionContext for transaction " + gtx + " not found in transaction table");
+ }
+ List<VisitableCommand> modifications = transactionContext.getModifications();
+ if (modifications.size() == 0)
+ {
+ if (trace) log.trace("Transaction has not logged any modifications!");
+ return;
+ }
+ if (trace) log.trace("Cache loader modification list: " + modifications);
+ StoreModificationsBuilder modsBuilder = new StoreModificationsBuilder(getStatisticsEnabled());
+ for (VisitableCommand cacheCommand : modifications)
+ {
+ cacheCommand.acceptVisitor(null, modsBuilder);
+ }
+ if (trace)
+ {
+ log.trace("Converted method calls to cache loader modifications. List size: " + modsBuilder.modifications.size());
+ }
+ if (modsBuilder.modifications.size() > 0)
+ {
+ loader.prepare(gtx, modsBuilder.modifications, onePhase);
+
+ preparingTxs.put(gtx, modsBuilder.affectedKeys);
+ if (getStatisticsEnabled() && modsBuilder.putCount > 0)
+ {
+ txStores.put(gtx, modsBuilder.putCount);
+ }
+ }
+ }
+
+ public static class StoreModificationsBuilder extends AbstractVisitor
+ {
+
+ boolean generateStatistics;
+
+ int putCount;
+
+ Set<Object> affectedKeys = new HashSet<Object>();
+
+ List<Modification> modifications = new ArrayList<Modification>();
+
+ public StoreModificationsBuilder(boolean generateStatistics)
+ {
+ this.generateStatistics = generateStatistics;
+ }
+
+ @Override
+ public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable
+ {
+ if (generateStatistics) putCount++;
+ modifications.add(new Modification(Modification.ModificationType.PUT, command.getKey(), command.getValue()));
+ affectedKeys.add(command.getKey());
+ return null;
+ }
+
+ @Override
+ public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable
+ {
+ Map<Object, Object> map = command.getMap();
+ if (generateStatistics) putCount += map.size();
+ affectedKeys.addAll(map.keySet());
+ modifications.addAll(toModifications(map));
+ return null;
+ }
+
+ @Override
+ public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable
+ {
+ modifications.add(new Modification(Modification.ModificationType.REMOVE, command.getKey(), null));
+ affectedKeys.add(command.getKey());
+ return null;
+ }
+
+ @Override
+ public Object visitClearCommand(InvocationContext ctx, ClearCommand command) throws Throwable
+ {
+ modifications.add(new Modification(Modification.ModificationType.CLEAR, null, null));
+ return null;
+ }
+ }
+
+ @ManagedOperation
+ public void resetStatistics()
+ {
+ cacheStores = 0;
+ }
+
+ @ManagedOperation
+ public Map<String, Object> dumpStatistics()
+ {
+ Map<String, Object> retval = new HashMap<String, Object>();
+ retval.put("CacheLoaderStores", cacheStores);
+ return retval;
+ }
+
+ @ManagedAttribute
+ public boolean getStatisticsEnabled()
+ {
+ return statsEnabled;
+ }
+
+ @ManagedAttribute
+ public void setStatisticsEnabled(boolean enabled)
+ {
+ this.statsEnabled = enabled;
+ }
+
+ @ManagedAttribute(description = "number of cache loader stores")
+ public long getCacheLoaderStores()
+ {
+ return cacheStores;
+ }
+
+}
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/CacheStoreInterceptor.java
___________________________________________________________________
Name: svn:executable
+ *
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Deleted: core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/base/SkipCheckChainedInterceptor.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/base/SkipCheckChainedInterceptor.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/interceptors/base/SkipCheckChainedInterceptor.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -1,77 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * 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.jboss.starobrno.interceptors.base;
-
-import org.jboss.starobrno.commands.VisitableCommand;
-import org.jboss.starobrno.context.InvocationContext;
-
-/**
- * This interceptor will call {@link #skipInterception(org.jboss.cache.InvocationContext ,org.jboss.cache.commands.VisitableCommand)} before invoking each visit method
- * (and the {@link #handleDefault(org.jboss.cache.InvocationContext , org.jboss.cache.commands.VisitableCommand)} method). If
- * {@link #skipInterception(org.jboss.cache.InvocationContext ,org.jboss.cache.commands.VisitableCommand)} returns <tt>false</tt>, the invocation will be skipped
- * and passed up the interceptor chain instead.
- * <p/>
- * Instead of overriding visitXXX() methods, implementations should override their handleXXX() counterparts defined in this class
- * instead, as well as the {@link #skipInterception(org.jboss.cache.InvocationContext ,org.jboss.cache.commands.VisitableCommand)} method.
- * Also, instead of overriding {@link #handleDefault(org.jboss.cache.InvocationContext , org.jboss.cache.commands.VisitableCommand)}, implementors
- * should override {@link #handleAll(org.jboss.cache.InvocationContext , org.jboss.cache.commands.VisitableCommand)}.
- *
- * @author Mircea.Markus(a)jboss.com
- * @since 2.2
- */
-public abstract class SkipCheckChainedInterceptor extends CommandInterceptor
-{
-
- // TODO!!!
-
- @Override
- public final Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable
- {
- if (skipInterception(ctx, command))
- {
- return invokeNextInterceptor(ctx, command);
- }
- return handleAll(ctx, command);
- }
-
- /**
- * Default implementation, which just passes the call up the interceptor chain
- *
- * @param ctx invocation context
- * @param command command
- * @return return value
- * @throws Throwable in the event of problems
- */
- protected Object handleAll(InvocationContext ctx, VisitableCommand command) throws Throwable
- {
- return invokeNextInterceptor(ctx, command);
- }
-
- /**
- * Tests whether the command should be intercepted or not. This is invoked before any of the handleXXX() methods.
- *
- * @param ctx invocation context
- * @param command command
- * @return true if the invocation should skip the current interceptor and move on to the next in the chain, false otherwise.
- */
- protected abstract boolean skipInterception(InvocationContext ctx, VisitableCommand command);
-}
\ No newline at end of file
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractCacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -124,7 +124,7 @@
switch (m.getType())
{
case PUT:
- put(m.getKey(), (V)m.getValue());
+ put((K)m.getKey(), (V)m.getValue());
break;
case REMOVE:
remove(m.getKey());
Added: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractDelegatingCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractDelegatingCacheLoader.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractDelegatingCacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,155 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.loader;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.List;
+
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+import org.jboss.starobrno.marshall.EntryData;
+
+/**
+ * AbstractDelegatingCacheLoader provides standard functionality for a cache loader that simply delegates each
+ * operation defined in the cache loader interface to the underlying cache loader, basically acting as a proxy to the
+ * real cache loader.
+ * <p/>
+ * Any cache loader implementation that extends this class would be required to override any of the methods in
+ * order to provide a different or added behaviour.
+ *
+ * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
+ */
+public abstract class AbstractDelegatingCacheLoader<K,V> extends AbstractCacheLoader<K,V>
+{
+ private CacheLoader<K,V> cacheLoader;
+
+ public AbstractDelegatingCacheLoader(CacheLoader<K,V> cacheLoader)
+ {
+ this.cacheLoader = cacheLoader;
+ }
+
+ public void clear()
+ {
+ cacheLoader.clear();
+ }
+
+ public void commit(Object tx)
+ {
+ cacheLoader.commit(tx);
+ }
+
+ public void create()
+ {
+ cacheLoader.create();
+ }
+
+ public void destroy()
+ {
+ cacheLoader.destroy();
+ }
+
+ public boolean exists(Object key)
+ {
+ return cacheLoader.exists(key);
+ }
+
+ public V get(Object key)
+ {
+ return cacheLoader.get(key);
+ }
+
+ public List<EntryData<K, V>> getAllEntries()
+ {
+ return cacheLoader.getAllEntries();
+ }
+
+ public IndividualCacheLoaderConfig getConfig()
+ {
+ return cacheLoader.getConfig();
+ }
+
+ public void loadEntireState(ObjectOutputStream os)
+ {
+ cacheLoader.loadEntireState(os);
+ }
+
+ public void prepare(Object tx, List<Modification> modifications, boolean one_phase)
+ {
+ cacheLoader.prepare(tx, modifications, one_phase);
+ }
+
+ public V put(K key, V value)
+ {
+ return cacheLoader.put(key, value);
+ }
+
+ public void put(List<Modification> modifications)
+ {
+ cacheLoader.put(modifications);
+ }
+
+ public V remove(Object key)
+ {
+ return cacheLoader.remove(key);
+ }
+
+ public void rollback(Object tx)
+ {
+ cacheLoader.rollback(tx);
+ }
+
+ public void setCache(CacheSPI<K, V> c)
+ {
+ cacheLoader.setCache(c);
+ }
+
+ public void setConfig(IndividualCacheLoaderConfig config)
+ {
+ cacheLoader.setConfig(config);
+ }
+
+ public void start()
+ {
+ cacheLoader.start();
+ }
+
+ public void stop()
+ {
+ cacheLoader.stop();
+ }
+
+ public void storeEntireState(ObjectInputStream is)
+ {
+ cacheLoader.storeEntireState(is);
+ }
+
+ public CacheLoader<K,V> getCacheLoader()
+ {
+ return cacheLoader;
+ }
+
+ public void setCacheLoader(CacheLoader<K,V> cacheLoader)
+ {
+ this.cacheLoader = cacheLoader;
+ }
+}
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AbstractDelegatingCacheLoader.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoader.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,341 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.loader;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.util.Immutables;
+import org.jboss.starobrno.CacheException;
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+
+/**
+ * The AsyncCacheLoader is a delegating cache loader that extends
+ * AbstractDelegatingCacheLoader overriding methods to that should not
+ * just delegate the operation to the underlying cache loader.
+ * <p/>
+ * Read operations are done synchronously, while write (CRUD - Create, Remove,
+ * Update, Delete) operations are done asynchronously. There is no provision
+ * for exception handling at the moment for problems encountered with the
+ * underlying CacheLoader during a CRUD operation, and the exception is just
+ * logged.
+ * <p/>
+ * When configuring the CacheLoader, use the following attribute:
+ * <p/>
+ * <code>
+ * <attribute name="CacheLoaderAsynchronous">true</attribute>
+ * </code>
+ * <p/>
+ * to define whether cache loader operations are to be asynchronous. If not
+ * specified, a cache loader operation is assumed synchronous.
+ * <p/>
+ * <p/>
+ * The following additional parameters are available:
+ * <dl>
+ * <dt>cache.async.batchSize</dt>
+ * <dd>Number of modifications to commit in one transaction, default is
+ * 100. The minimum batch size is 1.</dd>
+ * <dt>cache.async.pollWait</dt>
+ * <dd>How long to wait before processing an incomplete batch, in
+ * milliseconds. Default is 100. Set this to 0 to not wait before processing
+ * available records.</dd>
+ * <dt>cache.async.returnOld</dt>
+ * <dd>If <code>true</code>, this loader returns the old values from {@link
+ * #put} and {@link #remove} methods. Otherwise, these methods always return
+ * null. Default is true. <code>false</code> improves the performance of these
+ * operations.</dd>
+ * <dt>cache.async.queueSize</dt>
+ * <dd>Maximum number of entries to enqueue for asynchronous processing.
+ * Lowering this size may help prevent out-of-memory conditions. It also may
+ * help to prevent less records lost in the case of JVM failure. Default is
+ * 10,000 operations.</dd>
+ * <dt>cache.async.put</dt>
+ * <dd>If set to false, all {@link #put} operations will be processed
+ * synchronously, and then only the {@link #remove} operations will be
+ * processed asynchronously. This mode may be useful for processing
+ * expiration of messages within a separate thread and keeping other
+ * operations synchronous for reliability.
+ * </dd>
+ * <dt>cache.async.threadPoolSize</dt>
+ * <dd>The size of the async processor thread pool. Defaults to <tt>1</tt>. This
+ * property is new in JBoss Cache 3.0.</dd>
+ * </dl>
+ * For increased performance for many smaller transactions, use higher values
+ * for <code>cache.async.batchSize</code> and
+ * <code>cache.async.pollWait</code>. For larger sized records, use a smaller
+ * value for <code>cache.async.queueSize</code>.
+ *
+ * @author Manik Surtani (manik.surtani(a)jboss.com)
+ */
+public class AsyncCacheLoader<K,V> extends AbstractDelegatingCacheLoader<K,V>
+{
+
+ private static final Log log = LogFactory.getLog(AsyncCacheLoader.class);
+ private static final boolean trace = log.isTraceEnabled();
+
+ private static AtomicInteger threadId = new AtomicInteger(0);
+
+ /**
+ * Default limit on entries to process asynchronously.
+ */
+ private static final int DEFAULT_QUEUE_SIZE = 10000;
+
+ private AsyncCacheLoaderConfig config;
+ private ExecutorService executor;
+ private AtomicBoolean stopped = new AtomicBoolean(true);
+ private BlockingQueue<Modification> queue = new ArrayBlockingQueue<Modification>(DEFAULT_QUEUE_SIZE);
+ private List<Future> processorFutures;
+
+ public AsyncCacheLoader()
+ {
+ super(null);
+ }
+
+ public AsyncCacheLoader(CacheLoader<K,V> cacheLoader)
+ {
+ super(cacheLoader);
+ }
+
+ @Override
+ public void setConfig(IndividualCacheLoaderConfig base)
+ {
+ if (base instanceof AsyncCacheLoaderConfig)
+ {
+ config = (AsyncCacheLoaderConfig) base;
+ }
+ else
+ {
+ config = new AsyncCacheLoaderConfig(base);
+ }
+
+ if (config.getQueueSize() > 0)
+ {
+ queue = new ArrayBlockingQueue<Modification>(config.getQueueSize());
+ }
+
+ super.setConfig(base);
+ }
+
+ @Override
+ public V put(K key, V value)
+ {
+ if (config.getUseAsyncPut())
+ {
+ V oldValue = get(key);
+ Modification mod = new Modification(Modification.ModificationType.PUT, key, value);
+ enqueue(mod);
+ return oldValue;
+ }
+ else
+ {
+ return super.put(key, value);
+ }
+ }
+
+ @Override
+ public void put(List<Modification> modifications)
+ {
+ if (config.getUseAsyncPut())
+ {
+ for (Modification modification : modifications)
+ {
+ enqueue(modification);
+ }
+ }
+ else
+ {
+ super.put(modifications);
+ }
+ }
+
+ @Override
+ public V remove(Object key)
+ {
+ V oldValue = get(key);
+ Modification mod = new Modification(Modification.ModificationType.REMOVE, key, null);
+ enqueue(mod);
+ return oldValue;
+ }
+
+ @Override
+ public void start()
+ {
+ if (log.isInfoEnabled()) log.info("Async cache loader starting: " + this);
+ stopped.set(false);
+ super.start();
+ executor = Executors.newFixedThreadPool(config.getThreadPoolSize(), new ThreadFactory()
+ {
+ public Thread newThread(Runnable r)
+ {
+ Thread t = new Thread(r, "AsyncCacheLoader-" + threadId.getAndIncrement());
+ t.setDaemon(true);
+ return t;
+ }
+ });
+ processorFutures = new ArrayList<Future>(config.getThreadPoolSize());
+ for (int i = 0; i < config.getThreadPoolSize(); i++) processorFutures.add(executor.submit(new AsyncProcessor()));
+ }
+
+ @Override
+ public void stop()
+ {
+ stopped.set(true);
+ if (executor != null)
+ {
+ for (Future f : processorFutures) f.cancel(true);
+ executor.shutdown();
+ try
+ {
+ boolean terminated = executor.isTerminated();
+ while (!terminated)
+ {
+ terminated = executor.awaitTermination(60, TimeUnit.SECONDS);
+ }
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ executor = null;
+ super.stop();
+ }
+
+ private void enqueue(final Modification mod)
+ {
+ if (stopped.get())
+ {
+ throw new CacheException("AsyncCacheLoader stopped; no longer accepting more entries.");
+ }
+ if (trace) log.trace("Enqueuing modification " + mod);
+ try
+ {
+ queue.put(mod);
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ /**
+ * Processes (by batch if possible) a queue of {@link Modification}s.
+ *
+ * @author manik surtani
+ */
+ private class AsyncProcessor implements Runnable
+ {
+ // Modifications to invoke as a single put
+ private final List<Modification> mods = new ArrayList<Modification>(config.getBatchSize());
+
+ public void run()
+ {
+ while (!Thread.interrupted())
+ {
+ try
+ {
+ run0();
+ }
+ catch (InterruptedException e)
+ {
+ break;
+ }
+ }
+
+ try
+ {
+ if (trace) log.trace("process remaining batch " + mods.size());
+ put(mods);
+ if (trace) log.trace("process remaining queued " + queue.size());
+ while (!queue.isEmpty())
+ {
+ run0();
+ }
+ }
+ catch (InterruptedException e)
+ {
+ log.trace("remaining interrupted");
+ }
+ }
+
+ private void run0() throws InterruptedException
+ {
+ log.trace("Checking for modifications");
+ int i = queue.drainTo(mods, config.getBatchSize());
+ if (i == 0)
+ {
+ Modification m = queue.take();
+ mods.add(m);
+ }
+
+ if (trace)
+ {
+ log.trace("Calling put(List) with " + mods.size() + " modifications");
+ }
+ put(mods);
+ mods.clear();
+ }
+
+ private void put(List<Modification> mods)
+ {
+ try
+ {
+ AsyncCacheLoader.super.put(mods);
+ }
+ catch (Exception e)
+ {
+ if (log.isWarnEnabled()) log.warn("Failed to process async modifications: " + e);
+ if (log.isDebugEnabled()) log.debug("Exception: ", e);
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return super.toString() +
+ " delegate=[" + super.getCacheLoader() + "]" +
+ " stopped=" + stopped +
+ " batchSize=" + config.getBatchSize() +
+ " returnOld=" + config.getReturnOld() +
+ " asyncPut=" + config.getUseAsyncPut() +
+ " threadPoolSize=" + config.getThreadPoolSize() +
+ " queue.remainingCapacity()=" + queue.remainingCapacity() +
+ " queue.peek()=" + queue.peek();
+ }
+
+}
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoader.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoaderConfig.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoaderConfig.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoaderConfig.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.loader;
+
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+
+import java.util.Properties;
+
+public class AsyncCacheLoaderConfig extends IndividualCacheLoaderConfig
+{
+ /**
+ * The serialVersionUID
+ */
+ private static final long serialVersionUID = 5038037589485991681L;
+
+ private int batchSize = 100;
+ private boolean returnOld = true;
+ private int queueSize = 0;
+ private boolean useAsyncPut = true;
+ private int threadPoolSize = 1;
+
+ /**
+ * Default constructor.
+ */
+ public AsyncCacheLoaderConfig()
+ {
+ setClassName(AsyncCacheLoader.class.getName());
+ }
+
+ /**
+ * For use by {@link AsyncCacheLoader}.
+ *
+ * @param base generic config object created by XML parsing.
+ */
+ AsyncCacheLoaderConfig(IndividualCacheLoaderConfig base)
+ {
+ setClassName(AsyncCacheLoader.class.getName());
+ populateFromBaseConfig(base);
+ }
+
+ public int getThreadPoolSize()
+ {
+ return threadPoolSize;
+ }
+
+ public void setThreadPoolSize(int threadPoolSize)
+ {
+ testImmutability("threadPoolSize");
+ this.threadPoolSize = threadPoolSize;
+ }
+
+ public int getBatchSize()
+ {
+ return batchSize;
+ }
+
+ public void setBatchSize(int batchSize)
+ {
+ testImmutability("batchSize");
+ this.batchSize = batchSize;
+ }
+
+ public int getQueueSize()
+ {
+ return queueSize;
+ }
+
+ public void setQueueSize(int queueSize)
+ {
+ testImmutability("queueSize");
+ this.queueSize = queueSize;
+ }
+
+ public boolean getReturnOld()
+ {
+ return returnOld;
+ }
+
+ public void setReturnOld(boolean returnOld)
+ {
+ testImmutability("returnOld");
+ this.returnOld = returnOld;
+ }
+
+ public boolean getUseAsyncPut()
+ {
+ return useAsyncPut;
+ }
+
+ public void setUseAsyncPut(boolean useAsyncPut)
+ {
+ testImmutability("useAsyncPut");
+ this.useAsyncPut = useAsyncPut;
+ }
+
+ @Override
+ public void setProperties(Properties props)
+ {
+ super.setProperties(props);
+ String s;
+
+ s = props.getProperty("cache.async.batchSize");
+ if (s != null) batchSize = Integer.parseInt(s);
+ if (batchSize <= 0) throw new IllegalArgumentException("Invalid batch size: " + batchSize);
+
+ s = props.getProperty("cache.async.threadPoolSize");
+ if (s != null) threadPoolSize = Integer.parseInt(s);
+ if (threadPoolSize <= 0) throw new IllegalArgumentException("Invalid thread pool size: " + threadPoolSize);
+
+
+ s = props.getProperty("cache.async.returnOld");
+ if (s != null) returnOld = Boolean.valueOf(s);
+
+ s = props.getProperty("cache.async.queueSize");
+ if (s != null) queueSize = Integer.parseInt(s);
+
+ s = props.getProperty("cache.async.put");
+ if (s != null) useAsyncPut = Boolean.valueOf(s);
+
+
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof AsyncCacheLoaderConfig && equalsExcludingProperties(obj))
+ {
+ AsyncCacheLoaderConfig other = (AsyncCacheLoaderConfig) obj;
+ return (batchSize == other.batchSize)
+ && (queueSize == other.queueSize)
+ && (returnOld == other.returnOld)
+ && (useAsyncPut == other.useAsyncPut);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = hashCodeExcludingProperties();
+ result = 31 * result + batchSize;
+ result = 31 * result + queueSize;
+ result = 31 * result + (returnOld ? 0 : 1);
+ result = 31 * result + (useAsyncPut ? 0 : 1);
+ return result;
+ }
+
+ @Override
+ public AsyncCacheLoaderConfig clone() throws CloneNotSupportedException
+ {
+ return (AsyncCacheLoaderConfig) super.clone();
+ }
+
+
+}
\ No newline at end of file
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/loader/AsyncCacheLoaderConfig.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoader.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -115,7 +115,7 @@
* node does not exist, all parent nodes from the root down are created
* automatically. Returns the old value.
*/
- V put(Object key, V value) ;
+ V put(K key, V value) ;
/**
* Removes everything from this cache-loader
@@ -139,6 +139,14 @@
/**
+ * Applies all modifications to the backend store.
+ * Changes may be applied in a single operation.
+ *
+ * @param modifications A List<Modification> of modifications
+ */
+ void put(List<Modification> modifications);
+
+ /**
* Prepares a list of modifications. For example, for a DB-based CacheLoader:
* <ol>
* <li>Create a local (JDBC) transaction
Added: core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,447 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.loader;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.starobrno.CacheException;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.ConfigurationException;
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig.SingletonStoreConfig;
+import org.jboss.starobrno.factories.ComponentRegistry;
+import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.factories.annotations.Start;
+import org.jboss.starobrno.factories.annotations.Stop;
+import org.jboss.starobrno.util.ReflectionUtil;
+
+/**
+ * Manages all cache loader functionality. This class is typically initialised with an XML DOM Element,
+ * represeting a cache loader configuration, or a {@link org.jboss.cache.config.CacheLoaderConfig} object.
+ * <p/>
+ * Usage:
+ * <p/>
+ * <code>
+ * CacheLoaderManager manager = new CacheLoaderManager();
+ * manager.setConfig(myXmlSnippet, myTreeCache);
+ * CacheLoader loader = manager.getCacheLoader();
+ * </code>
+ * <p/>
+ * The XML configuration passed in would typically look like:
+ * <p/>
+ * <code><![CDATA[
+ * <p/>
+ * <config>
+ * <passivation>false</passivation>
+ * <preload>/</preload>
+ * <p/>
+ * <cacheloader>
+ * <class>org.jboss.cache.loader.FileCacheLoader</class>
+ * <async>true</async>
+ * <fetchPersistentState>false</fetchPersistentState>
+ * <ignoreModifications>false</ignoreModifications>
+ * <properties>
+ * location=/tmp/file
+ * </properties>
+ * </cacheloader>
+ * </config>
+ * ]]>
+ * </code>
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik(a)jboss.org)</a>
+ * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
+ */
+public class CacheLoaderManager
+{
+ private static final Log log = LogFactory.getLog(CacheLoaderManager.class);
+ private CacheLoaderConfig config;
+ private CacheSPI<Object,Object> cache;
+ private CacheLoader<Object,Object> loader;
+ private boolean fetchPersistentState;
+ private Configuration configuration;
+ private ComponentRegistry registry;
+
+ @Inject
+ public void injectDependencies(CacheSPI<Object, Object> cache, Configuration configuration, ComponentRegistry registry)
+ {
+ // TODO: Inject CacheSPI once we have the cache loaders not relying on a tree structure
+ this.config = configuration.getCacheLoaderConfig();
+// this.cache = cache;
+ this.configuration = configuration;
+ this.registry = registry;
+
+ if (config != null)
+ {
+ try
+ {
+ loader = createCacheLoader();
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to create cache loaders", e);
+ }
+ }
+ }
+
+ /**
+ * Sets a configuration object and creates a cacheloader accordingly. Primarily used for testing.
+ *
+ * @param config
+ * @param cache
+ * @throws CacheException
+ */
+ public void setConfig(CacheLoaderConfig config, CacheSPI<Object,Object> cache, Configuration configuration) throws CacheException
+ {
+ this.config = config == null ? configuration.getCacheLoaderConfig() : config;
+ this.cache = cache;
+ this.configuration = configuration;
+
+ if (config != null)
+ {
+ try
+ {
+ loader = createCacheLoader();
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to create cache loaders", e);
+ }
+ }
+ }
+
+ /**
+ * Creates the cache loader based on a cache loader config passed in.
+ *
+ * @return a configured cacheloader
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ * @throws ClassNotFoundException
+ */
+ private CacheLoader<Object, Object> createCacheLoader() throws Exception
+ {
+ CacheLoader<Object,Object> tmpLoader;
+ // if we only have a single cache loader configured in the chaining cacheloader then
+ // don't use a chaining cache loader at all.
+
+ ArrayList<IndividualCacheLoaderConfig> finalConfigs =
+ new ArrayList<IndividualCacheLoaderConfig>();
+
+ // also if we are using passivation then just directly use the first cache loader.
+ if (config.useChainingCacheLoader())
+ {
+ // create chaining cache loader.
+ ChainingCacheLoader<Object,Object> ccl = new ChainingCacheLoader<Object,Object>();
+ tmpLoader = ccl;
+ Iterator<IndividualCacheLoaderConfig> it = config.getIndividualCacheLoaderConfigs().iterator();
+
+ // only one cache loader may have fetchPersistentState to true.
+ int numLoadersWithFetchPersistentState = 0;
+ while (it.hasNext())
+ {
+ CacheLoaderConfig.IndividualCacheLoaderConfig cfg = (CacheLoaderConfig.IndividualCacheLoaderConfig) it.next();
+ if (cfg.isFetchPersistentState())
+ {
+ numLoadersWithFetchPersistentState++;
+ fetchPersistentState = true;
+ }
+ if (numLoadersWithFetchPersistentState > 1)
+ {
+ throw new Exception("Invalid cache loader configuration!! Only ONE cache loader may have fetchPersistentState set to true. Cache will not start!");
+ }
+
+ assertNotSingletonAndShared(cfg);
+
+ CacheLoader<Object,Object> l = createCacheLoader(cfg, cache);
+ cfg = l.getConfig();
+ finalConfigs.add(cfg);
+ // Only loaders that deal w/ state transfer factor into
+ // whether the overall chain supports ExtendedCacheLoader
+ ccl.addCacheLoader(l, cfg);
+
+ }
+ }
+ else
+ {
+ CacheLoaderConfig.IndividualCacheLoaderConfig cfg = config.getIndividualCacheLoaderConfigs().get(0);
+ tmpLoader = createCacheLoader(cfg, cache);
+ finalConfigs.add(tmpLoader.getConfig() == null ? cfg : tmpLoader.getConfig());
+ fetchPersistentState = cfg.isFetchPersistentState();
+ assertNotSingletonAndShared(cfg);
+ }
+
+ // Update the config with those actually used by the loaders
+ ReflectionUtil.setValue(config, "accessible", true);
+ config.setIndividualCacheLoaderConfigs(finalConfigs);
+
+ return tmpLoader;
+ }
+
+ private void assertNotSingletonAndShared(IndividualCacheLoaderConfig cfg)
+ {
+ SingletonStoreConfig ssc = cfg.getSingletonStoreConfig();
+ if (ssc != null && ssc.isSingletonStoreEnabled() && config.isShared())
+ throw new ConfigurationException("Invalid cache loader configuration!! If a cache loader is configured as a singleton, the cache loader cannot be shared in a cluster!");
+ }
+
+ /**
+ * Creates the cache loader based on the configuration.
+ *
+ * @param cfg
+ * @param cache
+ * @return a cache loader
+ * @throws Exception
+ */
+ @SuppressWarnings("deprecation")
+ private CacheLoader<Object, Object> createCacheLoader(CacheLoaderConfig.IndividualCacheLoaderConfig cfg, CacheSPI<Object, Object> cache) throws Exception
+ {
+ // create loader
+ CacheLoader<Object, Object> tmpLoader = cfg.getCacheLoader() == null ? createInstance(cfg.getClassName()) : cfg.getCacheLoader();
+
+ if (tmpLoader != null)
+ {
+ // async?
+ if (cfg.isAsync())
+ {
+ CacheLoader<Object, Object> asyncDecorator;
+ asyncDecorator = new AsyncCacheLoader<Object, Object>(tmpLoader);
+ tmpLoader = asyncDecorator;
+ }
+
+ if (cfg.isIgnoreModifications())
+ {
+ AbstractDelegatingCacheLoader<Object, Object> readOnlyDecorator;
+ readOnlyDecorator = new ReadOnlyDelegatingCacheLoader<Object, Object>(tmpLoader);
+ tmpLoader = readOnlyDecorator;
+ }
+
+ // singleton?
+ SingletonStoreConfig ssc = cfg.getSingletonStoreConfig();
+ if (ssc != null && ssc.isSingletonStoreEnabled())
+ {
+ Object decorator = createInstance(ssc.getSingletonStoreClass());
+
+ /* class providing singleton store functionality must extend AbstractDelegatingCacheLoader so that
+ * underlying cacheloader can be set. */
+ if (decorator instanceof AbstractDelegatingCacheLoader)
+ {
+ @SuppressWarnings("unchecked")
+ AbstractDelegatingCacheLoader<Object, Object> singletonDecorator = (AbstractDelegatingCacheLoader<Object, Object>) decorator;
+ /* set the cache loader to where calls will be delegated by the class providing the singleton
+ * store functionality. */
+ singletonDecorator.setCacheLoader(tmpLoader);
+ tmpLoader = singletonDecorator;
+ }
+ else
+ {
+ throw new Exception("Invalid cache loader configuration!! Singleton store implementation class must extend org.jboss.cache.loader.AbstractDelegatingCacheLoader");
+ }
+ }
+
+ // load props
+ tmpLoader.setConfig(cfg);
+
+ setCacheInLoader(cache, tmpLoader);
+ // we should not be creating/starting the cache loader here - this should be done in the separate
+ // startCacheLoader() method.
+ // tmpLoader.create();
+ // tmpLoader.start();
+ }
+ return tmpLoader;
+ }
+
+ /**
+ * Sets the cache instance associated with the given cache loader. This method was created for testing purpouses
+ * so that it can be overriden in the mock version of the CacheLoaderManager.
+ *
+ * @param c instance of cache to be set in cache loader
+ * @param loader cache loader to which assign the cache instance
+ */
+ protected void setCacheInLoader(CacheSPI<Object,Object> c, CacheLoader<Object,Object> loader)
+ {
+ loader.setCache(c);
+ }
+
+ @SuppressWarnings("unchecked")
+ private CacheLoader<Object, Object> createInstance(String className) throws ClassNotFoundException, IllegalAccessException, InstantiationException
+ {
+ if (log.isTraceEnabled()) log.trace("instantiating class " + className);
+ Class<?> cl = Thread.currentThread().getContextClassLoader().loadClass(className);
+ return (CacheLoader<Object, Object>) cl.newInstance();
+ }
+
+ /**
+ * Performs a preload on the cache based on the cache loader preload configs used when configuring the cache.
+ *
+ * @throws Exception
+ */
+ @Start(priority = 50)
+ public void preloadCache() throws CacheException
+ {
+ if (loader != null)
+ {
+ if (config.getPreload() == null || config.getPreload().equals("")) return;
+ if (log.isDebugEnabled()) log.debug("preloading transient state from cache loader " + loader);
+ StringTokenizer st = new StringTokenizer(config.getPreload(), ",");
+ long start, stop, total;
+ start = System.currentTimeMillis();
+ while (st.hasMoreTokens())
+ {
+ String tok = st.nextToken().trim();
+ if (log.isTraceEnabled()) log.trace("preloading " + tok);
+ preload(tok);
+ }
+
+ stop = System.currentTimeMillis();
+ total = stop - start;
+ if (log.isDebugEnabled())
+ {
+ log.debug("preloading transient state from cache loader was successful (in " + total + " milliseconds)");
+ }
+ }
+ }
+
+ /**
+ * Preloads a specific Fqn into the cache from the configured cacheloader
+ *
+ * @param fqn fqn to preload
+ * @param preloadParents whether we preload parents
+ * @param preloadChildren whether we preload children
+ * @throws CacheException if we are unable to preload
+ */
+ public void preload(String key) throws CacheException
+ {
+
+ cache.getInvocationContext().getOptionOverrides().setSkipDataGravitation(true);
+ cache.getInvocationContext().getOptionOverrides().setSkipCacheStatusCheck(true);
+ // 1. Load the attributes first
+ // but this will go down the entire damn chain!! :S
+ cache.get(key);
+ }
+
+ /**
+ * Returns the configuration element of the cache loaders
+ */
+ public CacheLoaderConfig getCacheLoaderConfig()
+ {
+ return config;
+ }
+
+ /**
+ * Returns the cache loader
+ */
+ public CacheLoader<Object, Object> getCacheLoader()
+ {
+ return loader;
+ }
+
+ /**
+ * Tests if we're using passivation
+ */
+ public boolean isPassivation()
+ {
+ return config.isPassivation();
+ }
+
+ /**
+ * Returns true if at least one of the configured cache loaders has set fetchPersistentState to true.
+ */
+ public boolean isFetchPersistentState()
+ {
+ return fetchPersistentState;
+ }
+
+ @Stop
+ public void stopCacheLoader()
+ {
+ if (loader != null)
+ {
+ // stop the cache loader
+ loader.stop();
+ // destroy the cache loader
+ loader.destroy();
+ }
+ }
+
+ @Start
+ public void startCacheLoader() throws CacheException
+ {
+ if (config == null) config = configuration.getCacheLoaderConfig();
+
+ if (config != null && loader == null)
+ {
+ try
+ {
+ loader = createCacheLoader();
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to create cache loaders", e);
+ }
+ }
+
+
+ if (loader != null)
+ {
+ try
+ {
+ // wire any deps.
+ registry.wireDependencies(loader);
+
+ // create the cache loader
+ loader.create();
+ // start the cache loader
+ loader.start();
+
+ purgeLoaders(false);
+ }
+ catch (Exception e)
+ {
+ throw new CacheException("Unable to start cache loaders", e);
+ }
+ fetchPersistentState = fetchPersistentState || (loader.getConfig() != null && loader.getConfig().isFetchPersistentState());
+ fetchPersistentState = fetchPersistentState || (config != null && config.isFetchPersistentState());
+ }
+ }
+
+ public void purgeLoaders(boolean force) throws Exception
+ {
+ if ((loader instanceof ChainingCacheLoader) && !force)
+ {
+ ((ChainingCacheLoader<?,?>) loader).purgeIfNecessary();
+ }
+ else
+ {
+ CacheLoaderConfig.IndividualCacheLoaderConfig first = getCacheLoaderConfig().getFirstCacheLoaderConfig();
+ if (force ||
+ (first != null && first.isPurgeOnStartup()))
+ {
+ loader.clear();
+ }
+ }
+ }
+}
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/loader/CacheLoaderManager.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Added: core/branches/flat/src/main/java/org/jboss/starobrno/loader/ChainingCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/ChainingCacheLoader.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/ChainingCacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,389 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.loader;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+import org.jboss.starobrno.factories.ComponentRegistry;
+import org.jboss.starobrno.factories.annotations.Inject;
+import org.jboss.starobrno.marshall.EntryData;
+
+/**
+ * This decorator is used whenever more than one cache loader is configured. READ operations are directed to
+ * each of the cache loaders (in the order which they were configured) until a non-null (or non-empty in the case
+ * of retrieving collection objects) result is achieved.
+ * <p/>
+ * WRITE operations are propagated to ALL registered cacheloaders that specified set ignoreModifications to false.
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik(a)jboss.org)</a>
+ */
+public class ChainingCacheLoader<K,V> extends AbstractCacheLoader<K,V>
+{
+
+ private final List<CacheLoader<K,V>> cacheLoaders = new ArrayList<CacheLoader<K,V>>(2);
+ private final List<CacheLoader<K,V>> writeCacheLoaders = new ArrayList<CacheLoader<K,V>>(2);
+ private final List<CacheLoaderConfig.IndividualCacheLoaderConfig> cacheLoaderConfigs = new ArrayList<CacheLoaderConfig.IndividualCacheLoaderConfig>(2);
+ private ComponentRegistry registry;
+
+ /**
+ * Sets the configuration. Will be called before {@link #create()} and {@link #start()}
+ *
+ * @param config ignored
+ */
+ public void setConfig(IndividualCacheLoaderConfig config)
+ {
+ // don't do much here?
+ }
+
+ public IndividualCacheLoaderConfig getConfig()
+ {
+ return null;
+ }
+
+ @Inject
+ public void injectDependencies(ComponentRegistry registry)
+ {
+ this.registry = registry;
+ }
+
+
+ public V get(Object key)
+ {
+ V answer = null;
+ for (CacheLoader<K,V> l : cacheLoaders)
+ {
+ answer = l.get(key);
+ if (answer != null) break;
+ }
+ return answer;
+ }
+
+ /**
+ * Checks whether the CacheLoader has a node with Fqn
+ *
+ * @param name
+ * @return True if node exists, false otherwise
+ */
+ public boolean exists(Object key)
+ {
+ boolean answer = false;
+ for (CacheLoader<K,V> l : cacheLoaders)
+ {
+ answer = l.exists(key);
+ if (answer) break;
+ }
+ return answer;
+ }
+
+ /**
+ * Inserts key and value into the attributes hashmap of the given node. If the node does not exist, all
+ * parent nodes from the root down are created automatically. Returns the old value
+ */
+ public V put(K key, V value)
+ {
+ V answer = null;
+ boolean isFirst = true;
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ {
+ V tAnswer = l.put(key, value);
+ if (isFirst)
+ {
+ answer = tAnswer;
+ isFirst = false;
+ }
+
+ }
+ return answer;
+ }
+
+ /**
+ * Inserts all modifications to the backend store. Overwrite whatever is already in
+ * the datastore.
+ *
+ * @param modifications A List<Modification> of modifications
+ * @throws Exception
+ */
+ @Override
+ public void put(List<Modification> modifications)
+ {
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ {
+ l.put(modifications);
+ }
+ }
+
+ /**
+ * Removes the given key and value. No-op if key doesn't exist.
+ * Returns the first response from the loader chain.
+ */
+ public V remove(Object key)
+ {
+ V answer = null;
+ boolean isFirst = true;
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ {
+ V tAnswer = l.remove(key);
+ if (isFirst)
+ {
+ answer = tAnswer;
+ isFirst = false;
+ }
+ }
+ return answer;
+ }
+
+ /**
+ * Prepare the modifications. For example, for a DB-based CacheLoader:
+ * <ol>
+ * <li>Create a local (JDBC) transaction
+ * <li>Associate the local transaction with <code>tx</code> (tx is the key)
+ * <li>Execute the coresponding SQL statements against the DB (statements derived from modifications)
+ * </ol>
+ * For non-transactional CacheLoader (e.g. file-based), this could be a null operation
+ *
+ * @param tx The transaction, just used as a hashmap key
+ * @param modifications List<Modification>, a list of all modifications within the given transaction
+ * @param one_phase Persist immediately and (for example) commit the local JDBC transaction as well. When true,
+ * we won't get a {@link #commit(Object)} or {@link #rollback(Object)} method call later
+ * @throws Exception
+ */
+ @Override
+ public void prepare(Object tx, List<Modification> modifications, boolean one_phase)
+ {
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ {
+ l.prepare(tx, modifications, one_phase);
+ }
+ }
+
+ /**
+ * Commit the transaction. A DB-based CacheLoader would look up the local JDBC transaction asociated
+ * with <code>tx</code> and commit that transaction<br/>
+ * Non-transactional CacheLoaders could simply write the data that was previously saved transiently under the
+ * given <code>tx</code> key, to (for example) a file system (note this only holds if the previous prepare() did
+ * not define one_phase=true
+ *
+ * @param tx
+ */
+ @Override
+ public void commit(Object tx)
+ {
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ {
+ l.commit(tx);
+ }
+ }
+
+ /**
+ * Roll the transaction back. A DB-based CacheLoader would look up the local JDBC transaction asociated
+ * with <code>tx</code> and roll back that transaction
+ *
+ * @param tx
+ */
+ @Override
+ public void rollback(Object tx)
+ {
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ {
+ l.rollback(tx);
+ }
+ }
+
+
+ /**
+ * Creates individual cache loaders.
+ *
+ * @throws Exception
+ */
+ @Override
+ public void create()
+ {
+ Iterator<CacheLoader<K, V>> it = cacheLoaders.iterator();
+ Iterator<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgIt = cacheLoaderConfigs.iterator();
+ while (it.hasNext() && cfgIt.hasNext())
+ {
+ CacheLoader<K,V> cl = it.next();
+ CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgIt.next();
+ cl.setConfig(cfg);
+ registry.wireDependencies(cl);
+ cl.create();
+ }
+ }
+
+ @Override
+ public void start()
+ {
+ for (CacheLoader<K,V> cacheLoader : cacheLoaders)
+ {
+ cacheLoader.start();
+ }
+ }
+
+ @Override
+ public void stop()
+ {
+ for (CacheLoader<K,V> cacheLoader : cacheLoaders)
+ {
+ cacheLoader.stop();
+ }
+ }
+
+ @Override
+ public void destroy()
+ {
+ for (CacheLoader<K,V> cacheLoader : cacheLoaders)
+ {
+ cacheLoader.destroy();
+ }
+ }
+ @Override
+ public void loadEntireState(ObjectOutputStream os)
+ {
+ Iterator<CacheLoader<K, V>> i = cacheLoaders.iterator();
+ Iterator<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgs = cacheLoaderConfigs.iterator();
+ while (i.hasNext() && cfgs.hasNext())
+ {
+ CacheLoader<K,V> l = i.next();
+ CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgs.next();
+ if (cfg.isFetchPersistentState())
+ {
+ l.loadEntireState(os);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void storeEntireState(ObjectInputStream is)
+ {
+ Iterator<CacheLoader<K, V>> i = writeCacheLoaders.iterator();
+ Iterator<CacheLoaderConfig.IndividualCacheLoaderConfig> cfgs = cacheLoaderConfigs.iterator();
+ while (i.hasNext())
+ {
+ CacheLoader<K,V> l = i.next();
+ CacheLoaderConfig.IndividualCacheLoaderConfig cfg = cfgs.next();
+ if (cfg.isFetchPersistentState())
+ {
+ l.storeEntireState(is);
+ break;
+ }
+ }
+
+ }
+
+ /**
+ * Returns the number of cache loaders in the chain.
+ */
+ public int getSize()
+ {
+ return cacheLoaders.size();
+ }
+
+ /**
+ * Returns a List<CacheLoader> of individual cache loaders configured.
+ */
+ public List<CacheLoader<K,V>> getCacheLoaders()
+ {
+ return Collections.unmodifiableList(cacheLoaders);
+ }
+
+ /**
+ * Adds a cache loader to the chain (always added at the end of the chain)
+ *
+ * @param l the cache loader to add
+ * @param cfg and its configuration
+ */
+ public void addCacheLoader(CacheLoader<K, V> l, CacheLoaderConfig.IndividualCacheLoaderConfig cfg)
+ {
+ synchronized (this)
+ {
+ cacheLoaderConfigs.add(cfg);
+ cacheLoaders.add(l);
+
+ if (!cfg.isIgnoreModifications())
+ {
+ writeCacheLoaders.add(l);
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder buf = new StringBuilder("ChainingCacheLoader{");
+ Iterator<CacheLoader<K, V>> i = cacheLoaders.iterator();
+ Iterator<CacheLoaderConfig.IndividualCacheLoaderConfig> c = cacheLoaderConfigs.iterator();
+ int count = 0;
+ while (i.hasNext() && c.hasNext())
+ {
+ CacheLoader<K,V> loader = i.next();
+ CacheLoaderConfig.IndividualCacheLoaderConfig cfg = c.next();
+
+ buf.append(++count);
+ buf.append(": IgnoreMods? ");
+ buf.append(cfg.isIgnoreModifications());
+ buf.append(" CLoader: ");
+ buf.append(loader);
+ buf.append("; ");
+ }
+ buf.append("}");
+ return buf.toString();
+ }
+
+ public void purgeIfNecessary() throws Exception
+ {
+ Iterator<CacheLoader<K, V>> loaders = cacheLoaders.iterator();
+ Iterator<CacheLoaderConfig.IndividualCacheLoaderConfig> configs = cacheLoaderConfigs.iterator();
+
+ while (loaders.hasNext() && configs.hasNext())
+ {
+ CacheLoader<K,V> myLoader = loaders.next();
+ CacheLoaderConfig.IndividualCacheLoaderConfig myConfig = configs.next();
+
+ if (!myConfig.isIgnoreModifications() && myConfig.isPurgeOnStartup()) myLoader.clear();
+ }
+ }
+
+ public void clear()
+ {
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ l.clear();
+ }
+
+ public List<EntryData<K, V>> getAllEntries()
+ {
+ ArrayList<EntryData<K,V>> full = new ArrayList<EntryData<K,V>>();
+
+ for (CacheLoader<K,V> l : writeCacheLoaders)
+ full.addAll(l.getAllEntries());
+
+ return full;
+ }
+
+}
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/loader/ChainingCacheLoader.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/loader/FileCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/FileCacheLoader.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/FileCacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -202,7 +202,7 @@
}
}
- public V put(Object key, V value)
+ public V put(K key, V value)
{
lock(key);
try
Added: core/branches/flat/src/main/java/org/jboss/starobrno/loader/ReadOnlyDelegatingCacheLoader.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/loader/ReadOnlyDelegatingCacheLoader.java (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/loader/ReadOnlyDelegatingCacheLoader.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -0,0 +1,94 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * 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.jboss.starobrno.loader;
+
+import java.io.ObjectInputStream;
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides ignoreModifications features to all cache loaders.
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+public class ReadOnlyDelegatingCacheLoader<K,V> extends AbstractDelegatingCacheLoader<K,V>
+{
+ private static final Log log = LogFactory.getLog(ReadOnlyDelegatingCacheLoader.class);
+
+ public ReadOnlyDelegatingCacheLoader(CacheLoader cl)
+ {
+ super(cl);
+ }
+
+ @Override
+ public V put(K key, V value)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ return get(key);
+ }
+
+ @Override
+ public void put(List<Modification> modifications)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ }
+
+ @Override
+ public V remove(Object key)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ return get(key);
+ }
+
+ @Override
+ public void prepare(Object tx, List<Modification> modifications, boolean one_phase)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ }
+
+ @Override
+ public void commit(Object tx)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ }
+
+ @Override
+ public void rollback(Object tx)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ }
+
+ @Override
+ public void storeEntireState(ObjectInputStream is)
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ }
+
+ @Override
+ public void clear()
+ {
+ log.trace("Not delegating write operation to underlying cache loader");
+ }
+}
Property changes on: core/branches/flat/src/main/java/org/jboss/starobrno/loader/ReadOnlyDelegatingCacheLoader.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java 2008-11-20 04:05:09 UTC (rev 7177)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java 2008-11-20 04:06:04 UTC (rev 7178)
@@ -1,4 +1,4 @@
-package org.jboss.cache.api;
+package org.jboss.starobrno.tree.api;
import org.jboss.cache.transaction.DummyTransactionManager;
import org.jboss.cache.transaction.DummyTransactionManagerLookup;
16 years, 1 month