added dynamic region and jndi binding support

This commit is contained in:
David Turanski
2012-07-03 10:01:49 -04:00
parent 1467ec0668
commit bb34beb224
13 changed files with 490 additions and 157 deletions

View File

@@ -16,7 +16,9 @@
package org.springframework.data.gemfire;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -41,13 +43,15 @@ import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.CacheTransactionManager;
import com.gemstone.gemfire.cache.Declarable;
import com.gemstone.gemfire.cache.DynamicRegionFactory;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.TransactionListener;
import com.gemstone.gemfire.cache.TransactionWriter;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.datasource.ConfigProperty;
import com.gemstone.gemfire.internal.jndi.JNDIInvoker;
import com.gemstone.gemfire.pdx.PdxSerializable;
import com.gemstone.gemfire.pdx.PdxSerializer;
@@ -125,12 +129,81 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
if (messageSyncInterval != null) {
cacheImpl.setMessageSyncInterval(messageSyncInterval);
}
}
}
if (initializer != null) {
// Props are null because already configured in Spring
cacheImpl.setInitializer(initializer, null);
public static class DynamicRegionSupport {
private String diskDir;
private String poolName;
private Boolean persistent = Boolean.TRUE;
private Boolean registerInterest = Boolean.TRUE;
public String getDiskDir() {
return diskDir;
}
public void setDiskDir(String diskDir) {
this.diskDir = diskDir;
}
public Boolean getPersistent() {
return persistent;
}
public void setPersistent(Boolean persistent) {
this.persistent = persistent;
}
public Boolean getRegisterInterest() {
return registerInterest;
}
public void setRegisterInterest(Boolean registerInterest) {
this.registerInterest = registerInterest;
}
public String getPoolName() {
return poolName;
}
public void setPoolName(String poolName) {
this.poolName = poolName;
}
public void initializeDynamicRegionFactory() {
DynamicRegionFactory.Config config = null;
if (diskDir == null) {
config = new DynamicRegionFactory.Config(null, poolName, persistent, registerInterest);
}
else {
config = new DynamicRegionFactory.Config(new File(diskDir), poolName, persistent, registerInterest);
}
DynamicRegionFactory.get().open(config);
}
}
public static class JndiDataSource {
private Map<String, String> attributes;
private List<ConfigProperty> props;
public Map<String, String> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, String> attributes) {
this.attributes = attributes;
}
public List<ConfigProperty> getProps() {
return props;
}
public void setProps(List<ConfigProperty> props) {
this.props = props;
}
}
@@ -177,7 +250,13 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
protected TransactionWriter transactionWriter;
protected Declarable initializer;
protected Float evictionHeapPercentage;
protected Float criticalHeapPercentage;
protected DynamicRegionSupport dynamicRegionSupport;
protected List<JndiDataSource> jndiDataSources;
@Override
public void afterPropertiesSet() throws Exception {
@@ -203,6 +282,9 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
msg = "Retrieved existing";
}
catch (CacheClosedException ex) {
initializeDynamicRegionFactory();
Object factory = createFactory(cfgProps);
// GemFire 6.6 specific options
@@ -238,16 +320,52 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
log.debug("Initialized cache from " + cacheXml);
}
}
setHeapPercentages();
registerTransactionListeners();
registerTransactionWriter();
registerJndiDataSources();
}
finally {
th.setContextClassLoader(oldTCCL);
}
}
private void registerJndiDataSources() {
if (jndiDataSources != null) {
for (JndiDataSource jndiDataSource : jndiDataSources) {
JNDIInvoker.mapDatasource(jndiDataSource.getAttributes(), jndiDataSource.getProps());
}
}
}
/**
* If dynamic regions are enabled, create a DynamicRegionFactory before
* creating the cache
*/
private void initializeDynamicRegionFactory() {
if (dynamicRegionSupport != null) {
dynamicRegionSupport.initializeDynamicRegionFactory();
}
}
private void setHeapPercentages() {
if (criticalHeapPercentage != null) {
Assert.isTrue(criticalHeapPercentage > 0.0 && criticalHeapPercentage <= 100.0,
"invalid value specified for criticalHeapPercentage :" + criticalHeapPercentage
+ ". Must be > 0.0 and <= 100.0");
cache.getResourceManager().setCriticalHeapPercentage(criticalHeapPercentage);
}
if (evictionHeapPercentage != null) {
Assert.isTrue(evictionHeapPercentage > 0.0 && evictionHeapPercentage <= 100.0,
"invalid value specified for evictionHeapPercentage :" + evictionHeapPercentage
+ ". Must be > 0.0 and <= 100.0");
cache.getResourceManager().setEvictionHeapPercentage(evictionHeapPercentage);
}
}
/**
* Register a transaction writer if declared
*/
@@ -471,6 +589,14 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
this.searchTimeout = searchTimeout;
}
public void setEvictionHeapPercentage(Float evictionHeapPercentage) {
this.evictionHeapPercentage = evictionHeapPercentage;
}
public void setCriticalHeapPercentage(Float criticalHeapPercentage) {
this.criticalHeapPercentage = criticalHeapPercentage;
}
public void setTransactionListeners(List<TransactionListener> transactionListeners) {
this.transactionListeners = transactionListeners;
}
@@ -479,8 +605,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
this.transactionWriter = transactionWriter;
}
public void setInitializer(Declarable initializer) {
this.initializer = initializer;
public void setDynamicRegionSupport(DynamicRegionSupport dynamicRegionSupport) {
this.dynamicRegionSupport = dynamicRegionSupport;
}
public void setJndiDataSources(List<JndiDataSource> jndiDataSources) {
this.jndiDataSources = jndiDataSources;
}
}

View File

@@ -22,13 +22,18 @@ import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import com.gemstone.gemfire.internal.datasource.ConfigProperty;
/**
* Parser for &lt;cache;gt; definitions.
@@ -52,15 +57,18 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser {
ParsingUtils.setPropertyReference(element, builder, "properties-ref", "properties");
ParsingUtils.setPropertyReference(element, builder, "pdx-serializer", "pdxSerializer");
ParsingUtils.setPropertyValue(element, builder, "pdx-disk-store", "pdxDiskStoreName");
ParsingUtils.setPropertyValue(element, builder, "pdx-persistent", "pdxPersistent");
ParsingUtils.setPropertyValue(element, builder, "pdx-read-serialized", "pdxReadSerialized");
ParsingUtils.setPropertyValue(element, builder, "pdx-ignore-unread-fields", "pdxIgnoreUnreadFields");
ParsingUtils.setPropertyValue(element, builder, "use-bean-factory-locator", "useBeanFactoryLocator");
ParsingUtils.setPropertyValue(element, builder, "copy-on-read", "copyOnRead");
ParsingUtils.setPropertyValue(element, builder, "lock-timeout", "lockTimeout");
ParsingUtils.setPropertyValue(element, builder, "lock-lease", "lockLease");
ParsingUtils.setPropertyValue(element, builder, "message-sync-interval", "messageSyncInterval");
ParsingUtils.setPropertyValue(element, builder, "search-timeout", "searchTimeout");
ParsingUtils.setPropertyValue(element, builder, "pdx-persistent");
ParsingUtils.setPropertyValue(element, builder, "pdx-read-serialized");
ParsingUtils.setPropertyValue(element, builder, "pdx-ignore-unread-fields");
ParsingUtils.setPropertyValue(element, builder, "use-bean-factory-locator");
ParsingUtils.setPropertyValue(element, builder, "copy-on-read");
ParsingUtils.setPropertyValue(element, builder, "lock-timeout");
ParsingUtils.setPropertyValue(element, builder, "lock-lease");
ParsingUtils.setPropertyValue(element, builder, "message-sync-interval");
ParsingUtils.setPropertyValue(element, builder, "search-timeout");
ParsingUtils.setPropertyValue(element, builder, "critical-heap-percentage");
ParsingUtils.setPropertyValue(element, builder, "eviction-heap-percentage");
List<Element> txListeners = DomUtils.getChildElementsByTagName(element, "transaction-listener");
if (!CollectionUtils.isEmpty(txListeners)) {
ManagedList<Object> transactionListeners = new ManagedList<Object>();
@@ -76,10 +84,80 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser {
ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, txWriter, builder));
}
Element initializer = DomUtils.getChildElementByTagName(element, "initializer");
if (initializer != null) {
builder.addPropertyValue("initializer",
ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, initializer, builder));
parseDynamicRegionFactory(element, builder);
parseJndiBindings(element, builder);
}
private void parseDynamicRegionFactory(Element element, BeanDefinitionBuilder builder) {
Element dynamicRegionFactory = DomUtils.getChildElementByTagName(element, "dynamic-region-factory");
if (dynamicRegionFactory != null) {
BeanDefinitionBuilder dynamicRegionSupport = buildDynamicRegionSupport(dynamicRegionFactory);
postProcessDynamicRegionSupport(element, dynamicRegionSupport);
builder.addPropertyValue("dynamicRegionSupport", dynamicRegionSupport.getBeanDefinition());
}
}
/**
* @param dynamicRegionSupport BDB for &lt;dynamic-region-factory&gt;
* element
*/
protected void postProcessDynamicRegionSupport(Element element, BeanDefinitionBuilder dynamicRegionSupport) {
}
private BeanDefinitionBuilder buildDynamicRegionSupport(Element dynamicRegionFactory) {
BeanDefinitionBuilder result = null;
if (dynamicRegionFactory != null) {
BeanDefinitionBuilder dynamicRegionSupport = BeanDefinitionBuilder
.genericBeanDefinition(CacheFactoryBean.DynamicRegionSupport.class);
String diskDir = dynamicRegionFactory.getAttribute("disk-dir");
if (StringUtils.hasText(diskDir)) {
dynamicRegionSupport.addPropertyValue("diskDir", diskDir);
}
String persistent = dynamicRegionFactory.getAttribute("persistent");
if (StringUtils.hasText(persistent)) {
dynamicRegionSupport.addPropertyValue("persistent", persistent);
}
String registerInterest = dynamicRegionFactory.getAttribute("register-interest");
if (StringUtils.hasText(registerInterest)) {
dynamicRegionSupport.addPropertyValue("registerInterest", registerInterest);
}
result = dynamicRegionSupport;
}
return result;
}
private void parseJndiBindings(Element element, BeanDefinitionBuilder builder) {
List<Element> jndiBindings = DomUtils.getChildElementsByTagName(element, "jndi-binding");
if (!CollectionUtils.isEmpty(jndiBindings)) {
ManagedList<Object> jndiDataSources = new ManagedList<Object>();
ManagedMap<String, String> jndiAttributes = new ManagedMap<String, String>();
for (Element jndiBinding : jndiBindings) {
BeanDefinitionBuilder jndiDataSource = BeanDefinitionBuilder
.genericBeanDefinition(CacheFactoryBean.JndiDataSource.class);
NamedNodeMap nnm = jndiBinding.getAttributes();
for (int i = 0; i < nnm.getLength(); i++) {
Attr attr = (Attr) nnm.item(i);
jndiAttributes.put(attr.getLocalName(), attr.getValue());
}
jndiDataSource.addPropertyValue("attributes", jndiAttributes);
List<Element> jndiProps = DomUtils.getChildElementsByTagName(element, "jndi-prop");
if (!CollectionUtils.isEmpty(jndiProps)) {
ManagedList<ConfigProperty> props = new ManagedList<ConfigProperty>();
for (Element jndiProp : jndiProps) {
String key = jndiProp.getAttribute("key");
String value = jndiProp.getNodeValue();
String type = StringUtils.hasText(jndiProp.getAttribute("type")) ? jndiProp
.getAttribute("type") : String.class.getName();
props.add(new ConfigProperty(key, value, type));
}
jndiDataSource.addPropertyValue("props", props);
}
jndiDataSources.add(jndiDataSource.getBeanDefinition());
}
builder.addPropertyValue("jndiDataSources", jndiDataSources);
}
}

View File

@@ -19,12 +19,14 @@ package org.springframework.data.gemfire.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Parser for &lt;client-cache;gt; definitions.
*
* @author Costin Leau
* @author David Turanski
*/
class ClientCacheParser extends CacheParser {
@@ -39,4 +41,12 @@ class ClientCacheParser extends CacheParser {
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName");
}
@Override
protected void postProcessDynamicRegionSupport(Element element, BeanDefinitionBuilder dynamicRegionSupport) {
String poolName = element.getAttribute("pool-name");
if (StringUtils.hasText(poolName)) {
dynamicRegionSupport.addPropertyValue("poolName", poolName);
}
}
}