Merge branch 'client-cache'

This commit is contained in:
Costin Leau
2011-08-24 21:24:48 +03:00
11 changed files with 383 additions and 49 deletions

View File

@@ -38,6 +38,7 @@ import com.gemstone.gemfire.GemFireException;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.distributed.DistributedMember;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.pdx.PdxSerializable;
@@ -57,8 +58,13 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @author Costin Leau
*/
public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean,
InitializingBean, FactoryBean<Cache>, PersistenceExceptionTranslator {
InitializingBean, FactoryBean<GemFireCache>, PersistenceExceptionTranslator {
/**
* Inner class to avoid a hard dependency on the GemFire 6.6 API.
*
* @author Costin Leau
*/
private class PdxOptions implements Runnable {
private CacheFactory factory;
@@ -69,6 +75,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
public void run() {
Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
factory.setPdxSerializer((PdxSerializer) pdxSerializer);
factory.setPdxDiskStore(pdxDiskStoreName);
factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields);
@@ -77,9 +84,9 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
}
}
private static final Log log = LogFactory.getLog(CacheFactoryBean.class);
protected final Log log = LogFactory.getLog(getClass());
private Cache cache;
private GemFireCache cache;
private Resource cacheXml;
private Properties properties;
private ClassLoader beanClassLoader;
@@ -89,11 +96,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
private String beanName;
private boolean useBeanFactoryLocator = true;
// PDX options
private Object pdxSerializer;
private Boolean pdxPersistent;
private Boolean pdxReadSerialized;
private Boolean pdxIgnoreUnreadFields;
private String pdxDiskStoreName;
protected Object pdxSerializer;
protected Boolean pdxPersistent;
protected Boolean pdxReadSerialized;
protected Boolean pdxIgnoreUnreadFields;
protected String pdxDiskStoreName;
public void afterPropertiesSet() throws Exception {
// initialize locator
@@ -104,7 +111,6 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
factoryLocator.afterPropertiesSet();
}
Properties cfgProps = mergeProperties();
CacheFactory factory = new CacheFactory(cfgProps);
// use the bean class loader to load Declarable classes
Thread th = Thread.currentThread();
@@ -115,19 +121,21 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
// first look for open caches
String msg = null;
try {
cache = CacheFactory.getAnyInstance();
cache = fetchCache();
msg = "Retrieved existing";
} catch (CacheClosedException ex) {
Object factory = createFactory(cfgProps);
// GemFire 6.6 specific options
if (pdxSerializer != null || pdxPersistent != null || pdxReadSerialized != null
|| pdxIgnoreUnreadFields != null || pdxDiskStoreName != null) {
Assert.isTrue(ClassUtils.isPresent("com.gemstone.gemfire.pdx.PdxSerializer", beanClassLoader),
"Cannot set PDX options since GemFire 6.6 not detected");
new PdxOptions(factory).run();
applyPdxOptions(factory);
}
// fall back to cache creation
cache = factory.create();
cache = createCache(factory);
msg = "Created";
}
@@ -136,7 +144,6 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
log.info("Connected to Distributed System [" + system.getName() + "=" + member.getId() + "@"
+ member.getHost() + "]");
log.info(msg + " GemFire v." + CacheFactory.getVersion() + " Cache [" + cache.getName() + "]");
// load/init cache.xml
@@ -146,10 +153,34 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
if (log.isDebugEnabled())
log.debug("Initialized cache from " + cacheXml);
} finally {
th.setContextClassLoader(oldTCCL);
}
}
/**
* Sets the PDX properties for the given object. Note this is implementation specific as it depends on the type
* of the factory passed in.
*
* @param factory
*/
protected void applyPdxOptions(Object factory) {
if (factory instanceof CacheFactory) {
new PdxOptions((CacheFactory) factory).run();
}
}
protected Object createFactory(Properties props) {
return new CacheFactory(props);
}
protected GemFireCache fetchCache() {
return CacheFactory.getAnyInstance();
}
protected GemFireCache createCache(Object factory) {
return ((CacheFactory) factory).create();
}
private Properties mergeProperties() {
Properties cfgProps = (properties != null ? (Properties) properties.clone() : new Properties());
@@ -184,11 +215,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
return null;
}
public Cache getObject() throws Exception {
public GemFireCache getObject() throws Exception {
return cache;
}
public Class<? extends Cache> getObjectType() {
public Class<? extends GemFireCache> getObjectType() {
return (cache != null ? cache.getClass() : Cache.class);
}
@@ -282,4 +313,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
public void setPdxDiskStoreName(String pdxDiskStoreName) {
this.pdxDiskStoreName = pdxDiskStoreName;
}
/**
* @return the beanFactory
*/
protected BeanFactory getBeanFactory() {
return beanFactory;
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.client;
import java.net.InetSocketAddress;
import java.util.List;
import java.util.Properties;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.pdx.PdxSerializer;
/**
* FactoryBean dedicated to creating client caches (caches for client JVMs).
* Acts an utility class (as client caches are a subset with a particular configuration of the generic cache).
*
* @author Costin Leau
*/
public class ClientCacheFactoryBean extends CacheFactoryBean {
/**
* Inner class to avoid a hard dependency on the GemFire 6.6 API.
*
* @author Costin Leau
*/
private class PdxOptions implements Runnable {
private ClientCacheFactory factory;
PdxOptions(ClientCacheFactory factory) {
this.factory = factory;
}
public void run() {
Assert.isAssignable(PdxSerializer.class, pdxSerializer.getClass(), "Invalid pdx serializer used");
factory.setPdxSerializer((PdxSerializer) pdxSerializer);
factory.setPdxDiskStore(pdxDiskStoreName);
factory.setPdxIgnoreUnreadFields(pdxIgnoreUnreadFields);
factory.setPdxPersistent(pdxPersistent);
factory.setPdxReadSerialized(pdxReadSerialized);
}
}
private String poolName;
private Pool pool;
@Override
protected GemFireCache createCache(Object factory) {
ClientCacheFactory ccf = (ClientCacheFactory) factory;
initializePool(ccf);
return ccf.create();
}
@Override
protected Object createFactory(Properties props) {
return new ClientCacheFactory(props);
}
@Override
protected GemFireCache fetchCache() {
return ClientCacheFactory.getAnyInstance();
}
private void initializePool(ClientCacheFactory ccf) {
Pool p = pool;
if (p == null && StringUtils.hasText(poolName)) {
BeanFactory beanFactory = getBeanFactory();
// try to eagerly initialize the pool name, if defined as a bean
if (beanFactory.isTypeMatch(poolName, Pool.class)) {
if (log.isDebugEnabled()) {
log.debug("Found bean definition for pool '" + poolName + "'. Eagerly initializing it...");
}
p = beanFactory.getBean(poolName, Pool.class);
}
}
if (p != null) {
// copy the pool settings - this way if the pool is not found, at least the cache will have a similar config
ccf.setPoolFreeConnectionTimeout(p.getFreeConnectionTimeout());
ccf.setPoolIdleTimeout(p.getIdleTimeout());
ccf.setPoolLoadConditioningInterval(p.getLoadConditioningInterval());
ccf.setPoolMaxConnections(p.getMaxConnections());
ccf.setPoolMinConnections(p.getMinConnections());
ccf.setPoolMultiuserAuthentication(p.getMultiuserAuthentication());
ccf.setPoolPingInterval(p.getPingInterval());
ccf.setPoolPRSingleHopEnabled(p.getPRSingleHopEnabled());
ccf.setPoolReadTimeout(p.getReadTimeout());
ccf.setPoolRetryAttempts(p.getRetryAttempts());
ccf.setPoolServerGroup(p.getServerGroup());
ccf.setPoolSocketBufferSize(p.getSocketBufferSize());
ccf.setPoolStatisticInterval(p.getStatisticInterval());
ccf.setPoolSubscriptionAckInterval(p.getSubscriptionAckInterval());
ccf.setPoolSubscriptionEnabled(p.getSubscriptionEnabled());
ccf.setPoolSubscriptionMessageTrackingTimeout(p.getSubscriptionMessageTrackingTimeout());
ccf.setPoolSubscriptionRedundancy(p.getSubscriptionRedundancy());
ccf.setPoolThreadLocalConnections(p.getThreadLocalConnections());
List<InetSocketAddress> locators = p.getLocators();
if (locators != null) {
for (InetSocketAddress inet : locators) {
ccf.addPoolLocator(inet.getHostName(), inet.getPort());
}
}
List<InetSocketAddress> servers = p.getServers();
if (locators != null) {
for (InetSocketAddress inet : servers) {
ccf.addPoolLocator(inet.getHostName(), inet.getPort());
}
}
}
}
/**
* Sets the pool name used by this client.
*
* @param poolName
*/
public void setPoolName(String poolName) {
Assert.hasText(poolName, "pool name is required");
this.poolName = poolName;
}
/**
* Sets the pool used by this client.
*
* @param pool
*/
public void setPool(Pool pool) {
Assert.notNull(pool, "pool cannot be null");
this.pool = pool;
}
@Override
protected void applyPdxOptions(Object factory) {
if (factory instanceof ClientCacheFactory) {
new PdxOptions((ClientCacheFactory) factory).run();
}
}
}

View File

@@ -55,7 +55,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean, Dis
private static final Log log = LogFactory.getLog(PoolFactoryBean.class);
// whether the pool has been created internaly or not
// whether the pool has been created internally or not
private boolean internalPool = true;
private Pool pool;

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2010-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.w3c.dom.Element;
/**
* Parser for &lt;client-cache;gt; definitions.
*
* @author Costin Leau
*/
class ClientCacheParser extends CacheParser {
@Override
protected Class<?> getBeanClass(Element element) {
return ClientCacheFactoryBean.class;
}
@Override
protected void doParse(Element element, BeanDefinitionBuilder builder) {
super.doParse(element, builder);
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName");
}
}

View File

@@ -27,6 +27,8 @@ class GemfireNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
registerBeanDefinitionParser("cache", new CacheParser());
registerBeanDefinitionParser("client-cache", new ClientCacheParser());
registerBeanDefinitionParser("lookup-region", new LookupRegionParser());
registerBeanDefinitionParser("replicated-region", new ReplicatedRegionParser());
registerBeanDefinitionParser("partitioned-region", new PartitionedRegionParser());