SGF-515 - Configure Geode Off-Heap Memory with annotations.
This commit is contained in:
@@ -18,17 +18,6 @@ package org.springframework.data.gemfire;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.AttributesFactory;
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.CacheListener;
|
||||
@@ -48,6 +37,17 @@ import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
|
||||
import com.gemstone.gemfire.cache.wan.GatewaySender;
|
||||
import com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Base class for FactoryBeans used to create GemFire {@link Region}s. Will try
|
||||
* to first locate the region (by name) and, in case none if found, proceed to
|
||||
@@ -71,6 +71,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
private boolean destroy = false;
|
||||
private boolean running;
|
||||
|
||||
private Boolean offHeap;
|
||||
private Boolean persistent;
|
||||
|
||||
private CacheListener<K, V>[] cacheListeners;
|
||||
@@ -110,18 +111,18 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
|
||||
RegionFactory<K, V> regionFactory = createRegionFactory(cache);
|
||||
|
||||
if (!ObjectUtils.isEmpty(gatewaySenders)) {
|
||||
for (Object gatewaySender : gatewaySenders) {
|
||||
regionFactory.addGatewaySenderId(((GatewaySender) gatewaySender).getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(asyncEventQueues)) {
|
||||
for (Object asyncEventQueue : asyncEventQueues) {
|
||||
regionFactory.addAsyncEventQueueId(((AsyncEventQueue) asyncEventQueue).getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(gatewaySenders)) {
|
||||
for (Object gatewaySender : gatewaySenders) {
|
||||
regionFactory.addGatewaySenderId(((GatewaySender) gatewaySender).getId());
|
||||
}
|
||||
}
|
||||
|
||||
if (!ObjectUtils.isEmpty(cacheListeners)) {
|
||||
for (CacheListener<K, V> listener : cacheListeners) {
|
||||
regionFactory.addCacheListener(listener);
|
||||
@@ -431,6 +432,7 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory
|
||||
*/
|
||||
protected void postProcess(RegionFactory<K, V> regionFactory) {
|
||||
regionFactory.setOffHeap(Boolean.TRUE.equals(offHeap));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -662,6 +664,37 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
this.gatewaySenders = gatewaySenders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable this {@link Region} to store it's data in off-heap memory.
|
||||
*
|
||||
* @param offHeap Boolean value indicating whether to enable off-heap memory for this Region.
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory#setOffHeap(boolean)
|
||||
*/
|
||||
public void setOffHeap(Boolean offHeap) {
|
||||
this.offHeap = offHeap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Boolean} value indicating whether off-heap memory was enabled for this {@link Region}.
|
||||
* Off-heap will be enabled if this method returns a non-{@literal null} {@link Boolean} value that evaluates
|
||||
* to {@literal true}.
|
||||
*
|
||||
* @return a {@link Boolean} value indicating whether off-heap is enabled for this {@link Region}.
|
||||
*/
|
||||
public Boolean getOffHeap() {
|
||||
return offHeap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean value indicating whether off-heap has been enabled for this {@link Region}.
|
||||
*
|
||||
* @return a {@literal boolean} value indicating whether off-heap has been enabled for this {@link Region}.
|
||||
* @see #getOffHeap()
|
||||
*/
|
||||
public boolean isOffHeap() {
|
||||
return Boolean.TRUE.equals(getOffHeap());
|
||||
}
|
||||
|
||||
public void setPersistent(Boolean persistent) {
|
||||
this.persistent = persistent;
|
||||
}
|
||||
@@ -778,5 +811,4 @@ public abstract class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K,
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2012 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* The EnableOffHeap annotation marks a Spring {@link org.springframework.context.annotation.Configuration @Configuration}
|
||||
* annotated class to configure and enable Apache Geode Off-Heap Memory support and data storage
|
||||
* in Geode's cache {@link com.gemstone.gemfire.cache.Region Regions}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.OffHeapConfiguration
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Import(OffHeapConfiguration.class)
|
||||
@SuppressWarnings("unused")
|
||||
public @interface EnableOffHeap {
|
||||
|
||||
/**
|
||||
* Specifies the size of off-heap memory in megabytes (m) or gigabytes (g). For example:
|
||||
*
|
||||
* <pre>
|
||||
* <code>
|
||||
* off-heap-memory-size=4096m
|
||||
* off-heap-memory-size=120g
|
||||
* </code>
|
||||
* </pre>
|
||||
*
|
||||
* Defaults to unset.
|
||||
*/
|
||||
String memorySize();
|
||||
|
||||
/**
|
||||
* Idenfitied the Regions by name in which the off-heap memory setting will be applied.
|
||||
*
|
||||
* Defaults to all Regions.
|
||||
*/
|
||||
String[] regionNames() default {};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2012 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.annotation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.data.gemfire.GenericRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.LocalRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.PartitionedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.ReplicatedRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport;
|
||||
import org.springframework.data.gemfire.util.ArrayUtils;
|
||||
import org.springframework.data.gemfire.util.CollectionUtils;
|
||||
import org.springframework.data.gemfire.util.PropertiesBuilder;
|
||||
|
||||
/**
|
||||
* The OffHeapConfiguration class is a Spring {@link org.springframework.context.annotation.ImportBeanDefinitionRegistrar}
|
||||
* capable of enabling GemFire cache {@link Region Regions} to use Off-Heap memory for data storage.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.config.annotation.EnableOffHeap
|
||||
* @see org.springframework.data.gemfire.config.annotation.support.EmbeddedServiceConfigurationSupport
|
||||
* @since 1.9.0
|
||||
*/
|
||||
public class OffHeapConfiguration extends EmbeddedServiceConfigurationSupport {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected Class getAnnotationType() {
|
||||
return EnableOffHeap.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
Map<String, Object> annotationAttributes, BeanDefinitionRegistry registry) {
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
OffHeapBeanFactoryPostProcessor.class);
|
||||
|
||||
builder.addConstructorArgValue(annotationAttributes.get("regionNames"));
|
||||
|
||||
registry.registerBeanDefinition(generateBeanName(OffHeapBeanFactoryPostProcessor.class),
|
||||
builder.getBeanDefinition());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@Override
|
||||
protected Properties toGemFireProperties(Map<String, Object> annotationAttributes) {
|
||||
PropertiesBuilder gemfireProperties = PropertiesBuilder.create();
|
||||
|
||||
gemfireProperties.setProperty("off-heap-memory-size", annotationAttributes.get("memorySize"));
|
||||
|
||||
return gemfireProperties.build();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected static class OffHeapBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
|
||||
|
||||
protected static final Set<String> REGION_FACTORY_BEAN_TYPES = new HashSet<String>(5);
|
||||
|
||||
static {
|
||||
REGION_FACTORY_BEAN_TYPES.add(ClientRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(GenericRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(LocalRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(PartitionedRegionFactoryBean.class.getName());
|
||||
REGION_FACTORY_BEAN_TYPES.add(ReplicatedRegionFactoryBean.class.getName());
|
||||
}
|
||||
|
||||
private final Set<String> regionNames;
|
||||
|
||||
protected OffHeapBeanFactoryPostProcessor(String[] regionNames) {
|
||||
this(CollectionUtils.asSet(ArrayUtils.nullSafeArray(regionNames, String.class)));
|
||||
}
|
||||
|
||||
protected OffHeapBeanFactoryPostProcessor(Set<String> regionNames) {
|
||||
this.regionNames = CollectionUtils.nullSafeSet(regionNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
for (String beanName : beanFactory.getBeanDefinitionNames()) {
|
||||
BeanDefinition bean = beanFactory.getBeanDefinition(beanName);
|
||||
|
||||
if (isTargetedRegionBean(beanName, bean, beanFactory)) {
|
||||
bean.getPropertyValues().addPropertyValue("offHeap", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTargetedRegionBean(String beanName, BeanDefinition bean,
|
||||
ConfigurableListableBeanFactory beanFactory) {
|
||||
|
||||
return (isRegionBean(bean) && isNamedRegion(beanName, bean, beanFactory));
|
||||
}
|
||||
|
||||
boolean isRegionBean(BeanDefinition bean) {
|
||||
return (bean != null && REGION_FACTORY_BEAN_TYPES.contains(bean.getBeanClassName()));
|
||||
}
|
||||
|
||||
boolean isNamedRegion(String beanName, BeanDefinition bean, ConfigurableListableBeanFactory beanFactory) {
|
||||
return (CollectionUtils.isEmpty(regionNames) || CollectionUtils.containsAny(regionNames,
|
||||
getBeanNames(beanName, bean, beanFactory)));
|
||||
}
|
||||
|
||||
Collection<String> getBeanNames(String beanName, BeanDefinition bean, BeanFactory beanFactory) {
|
||||
Collection<String> beanNames = new HashSet<String>();
|
||||
|
||||
beanNames.add(beanName);
|
||||
Collections.addAll(beanNames, beanFactory.getAliases(beanName));
|
||||
|
||||
PropertyValue regionName = bean.getPropertyValues().getPropertyValue("regionName");
|
||||
|
||||
if (regionName != null) {
|
||||
Object regionNameValue = regionName.getValue();
|
||||
|
||||
if (regionNameValue != null) {
|
||||
beanNames.add(regionNameValue.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return beanNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user