Implements SGF-88 - Region Shortcuts; Implements SGF-257 - Strict types in the SDG XSD for Region data-policy and shortcut attributes; Fixes SGF-258 - missing data-policy attribute for Partitioned Regions; Fixes SGF-263 - ineffective application of disk-synchronous attribute setting on Region bean definitions defined with SDG XML namespace.

This commit is contained in:
John Blum
2014-03-21 00:32:45 -07:00
parent 942c5ca7be
commit 1594c5f062
30 changed files with 2747 additions and 402 deletions

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.gemfire;
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.RegionFactory;
@@ -39,6 +39,28 @@ public class LocalRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
super.afterPropertiesSet();
}
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy == null || DataPolicy.NORMAL.equals(dataPolicy)) {
// NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL);
}
else if (DataPolicy.PRELOADED.equals(dataPolicy)) {
// NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED);
}
else if (DataPolicy.PERSISTENT_REPLICATE.equals(dataPolicy)
&& RegionShortcutWrapper.valueOf(getShortcut()).isPersistent()) {
regionFactory.setDataPolicy(dataPolicy);
}
else {
throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported for Local Regions.",
dataPolicy));
}
}
/**
* Resolves the Data Policy used by this "local" GemFire Region (i.e. locally Scoped; Scope.LOCAL) based on the
* enumerated value from com.gemstone.gemfire.cache.RegionShortcuts (LOCAL, LOCAL_PERSISTENT, LOCAL_HEAP_LRU,
@@ -53,25 +75,14 @@ public class LocalRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
*/
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
DataPolicy resolvedDataPolicy = null;
Assert.isTrue(resolvedDataPolicy != null || !StringUtils.hasText(dataPolicy),
String.format("Data Policy '%1$s' is invalid.", dataPolicy));
if (dataPolicy != null) {
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
}
if (resolvedDataPolicy == null || DataPolicy.NORMAL.equals(resolvedDataPolicy)) {
// NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL);
}
else if (DataPolicy.PRELOADED.equals(resolvedDataPolicy)) {
// NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED);
}
else {
throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported in Local Regions.",
dataPolicy));
}
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -28,32 +28,38 @@ import com.gemstone.gemfire.cache.RegionFactory;
public class PartitionedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
if (dataPolicy != null) {
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
// First, verify the GemFire version is 6.5 or Higher when Persistence is specified...
Assert.isTrue(!DataPolicy.PERSISTENT_PARTITION.equals(dataPolicy) || GemfireUtils.isGemfireVersion65OrAbove(),
String.format("Persistent PARTITION Regions can only be used from GemFire 6.5 onwards; current version is [%1$s].",
CacheFactory.getVersion()));
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:partitioned-region .../>)!
Assert.isTrue(resolvedDataPolicy.withPartitioning(), String.format(
"Data Policy '%1$s' is not supported in Partitioned Regions.", resolvedDataPolicy));
// Validate that the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
regionFactory.setDataPolicy(resolvedDataPolicy);
}
else if (isPersistent()) {
// first, check the presence of GemFire 6.5 or Higher
Assert.isTrue(GemfireUtils.isGemfireVersion65OrAbove(), String.format(
"Can define Persistent Partitioned Regions only from GemFire 6.5 onwards; current version is [%1$s]",
CacheFactory.getVersion()));
regionFactory.setDataPolicy(DataPolicy.PERSISTENT_PARTITION);
if (dataPolicy == null) {
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_PARTITION : DataPolicy.PARTITION);
}
else {
regionFactory.setDataPolicy(DataPolicy.PARTITION);
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:partitioned-region .../>)!
Assert.isTrue(dataPolicy.withPartitioning(), String.format(
"Data Policy '%1$s' is not supported in Partitioned Regions.", dataPolicy));
}
// Validate the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
regionFactory.setDataPolicy(dataPolicy);
}
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = null;
if (dataPolicy != null) {
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
}
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -24,6 +24,7 @@ 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;
@@ -35,12 +36,16 @@ import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheWriter;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.PartitionAttributes;
import com.gemstone.gemfire.cache.PartitionAttributesFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
import com.gemstone.gemfire.cache.wan.GatewaySender;
import com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes;
/**
* Base class for FactoryBeans used to create GemFire {@link Region}s. Will try
@@ -56,6 +61,7 @@ import com.gemstone.gemfire.cache.wan.GatewaySender;
* @author David Turanski
* @author John Blum
*/
@SuppressWarnings("unused")
public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean, SmartLifecycle {
protected final Log log = LogFactory.getLog(getClass());
@@ -74,16 +80,19 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
private CacheWriter<K, V> cacheWriter;
private DataPolicy dataPolicy;
private Object[] asyncEventQueues;
private Object[] gatewaySenders;
private RegionAttributes<K, V> attributes;
private RegionShortcut shortcut;
private Resource snapshot;
private Scope scope;
private String dataPolicy;
private String diskStoreName;
private String hubId;
@@ -94,27 +103,17 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
@Override
@SuppressWarnings("deprecation")
protected Region<K, V> lookupFallback(GemFireCache gemfireCache, String regionName) throws Exception {
Assert.isTrue(gemfireCache instanceof Cache, "Unable to create Regions from " + gemfireCache);
Cache cache = (Cache) gemfireCache;
RegionFactory<K, V> regionFactory;
if (attributes != null) {
// TODO refactor... AttributesFactory extended by the SDG RegionAttributesFactoryBean and used by all
// RegionFactoryBeans subclasses calls AttributesFactory.validateAttributes(..) before the RegionAttributes
// are created in the AttributesFactory.create() method, which is called by
// RegionAttributesFactoryBean.afterPropertiesSet() method.
AttributesFactory.validateAttributes(attributes);
regionFactory = cache.createRegionFactory(attributes);
}
else {
regionFactory = cache.createRegionFactory();
}
RegionFactory<K, V> regionFactory = createRegionFactory(cache);
if (hubId != null) {
enableGateway = (enableGateway == null || enableGateway);
Assert.isTrue(enableGateway, "hubId requires the enableGateway property to be true");
Assert.isTrue(enableGateway, "The 'hubId' requires the 'enableGateway' property to be true");
regionFactory.setGatewayHubId(hubId);
}
@@ -154,12 +153,12 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
regionFactory.setCacheWriter(cacheWriter);
}
resolveDataPolicy(regionFactory, persistent, dataPolicy);
if (diskStoreName != null) {
regionFactory.setDiskStoreName(diskStoreName);
}
resolveDataPolicy(regionFactory, persistent, dataPolicy);
if (scope != null) {
regionFactory.setScope(scope);
}
@@ -169,8 +168,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
"Lock Grantor only applies to a global scoped region.");
}
// get underlying AttributesFactory
postProcess(findAttributesFactory(regionFactory));
postProcess(regionFactory);
Region<K, V> region = (getParent() != null ? regionFactory.createSubregion(getParent(), regionName)
: regionFactory.create(regionName));
@@ -196,12 +194,279 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return region;
}
/**
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region/> elements
* are compatible.
* <p/>
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
* meta-data.
* @see #isPersistent()
* @see #isNotPersistent()
* @see com.gemstone.gemfire.cache.DataPolicy
*/
protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) {
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
}
else {
// NOTE otherwise, the Data Policy is not persistent, so...
Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
}
}
/**
* Determines whether the user explicitly set the 'persistent' attribute or not.
* <p/>
* @return a boolean value indicating whether the user explicitly set the 'persistent' attribute to true or false.
* @see #isPersistent()
* @see #isNotPersistent()
*/
protected boolean isPersistentUnspecified() {
return (persistent == null);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is true;
* false otherwise.
* @see #isNotPersistent()
* @see #isPersistentUnspecified()
*/
protected boolean isPersistent() {
return Boolean.TRUE.equals(persistent);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is false;
* false otherwise.
* @see #isPersistent()
* @see #isPersistentUnspecified()
*/
protected boolean isNotPersistent() {
return Boolean.FALSE.equals(persistent);
}
/**
* Creates an instance of RegionFactory using the given Cache instance used to configure and construct the Region
* created by this FactoryBean.
* <p/>
* @param cache the GemFire Cache instance.
* @return a RegionFactory used to configure and construct the Region created by this FactoryBean.
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory()
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory(com.gemstone.gemfire.cache.RegionAttributes)
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory(com.gemstone.gemfire.cache.RegionShortcut)
* @see com.gemstone.gemfire.cache.RegionFactory
*/
protected RegionFactory<K, V> createRegionFactory(final Cache cache) {
if (shortcut != null) {
RegionFactory<K, V> regionFactory = mergeRegionAttributes(
cache.<K, V>createRegionFactory(shortcut), attributes);
setDataPolicy(getDataPolicy(regionFactory));
return regionFactory;
}
else if (attributes != null) {
return cache.createRegionFactory(attributes);
}
else {
return cache.createRegionFactory();
}
}
/*
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
* @see com.gemstone.gemfire.cache.RegionFactory#attrsFactory
* @see com.gemstone.gemfire.cache.AttributesFactory#regionAttributes
* @see com.gemstone.gemfire.cache.RegionAttributes#getDataPolicy
* @see com.gemstone.gemfire.cache.DataPolicy
*/
@SuppressWarnings({ "deprecation", "unchecked"})
DataPolicy getDataPolicy(final RegionFactory regionFactory) {
// NOTE cannot pass RegionAttributes.class as the "targetType" on the second invocation of getFieldValue(..)
// since the "regionAttributes" field is naively of the implementation class type rather than the interface
// type... so much for programming to interfaces.
return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory", AttributesFactory.class),
"regionAttributes", null)).getDataPolicy();
}
/*
* (non-Javadoc)
*/
@SuppressWarnings("unchecked")
private <T> T getFieldValue(final Object source, final String fieldName, final Class<T> targetType) {
Field field = ReflectionUtils.findField(source.getClass(), fieldName, targetType);
ReflectionUtils.makeAccessible(field);
return (T) ReflectionUtils.getField(field, source);
}
/**
* Intelligently merges the given RegionAttributes with the configuration setting of the RegionFactory. This method
* is used to merge the RegionAttributes and PartitionAttributes with the RegionFactory that is created when the
* user specified a RegionShortcut. This method gets called by the createRegionFactory method depending upon
* the value passed to the Cache.createRegionFactory() method (i.e. whether there was a RegionShortcut specified
* or not).
* <p/>
* @param <K> the Class type fo the Region key.
* @param <V> the Class type of the Region value.
* @param regionFactory the GemFire RegionFactory used to configure and create the Region that is the product
* of this RegionFactoryBean.
* @param regionAttributes the RegionAttributes containing the Region configuration settings to merge to the
* RegionFactory.
* @return the RegionFactory with the configuration settings of the RegionAttributes merged.
* @see #hasUserSpecifiedEvictionAttributes(com.gemstone.gemfire.cache.RegionAttributes)
* @see #validateRegionAttributes(com.gemstone.gemfire.cache.RegionAttributes)
* @see com.gemstone.gemfire.cache.RegionAttributes
* @see com.gemstone.gemfire.cache.RegionFactory
*/
@SuppressWarnings("unchecked")
protected <K, V> RegionFactory<K, V> mergeRegionAttributes(final RegionFactory<K, V> regionFactory,
final RegionAttributes<K, V> regionAttributes) {
if (regionAttributes != null) {
// NOTE this validation may not be strictly required depending on how the RegionAttributes were "created",
// but...
validateRegionAttributes(regionAttributes);
regionFactory.setCloningEnabled(regionAttributes.getCloningEnabled());
regionFactory.setConcurrencyChecksEnabled(regionAttributes.getConcurrencyChecksEnabled());
regionFactory.setConcurrencyLevel(regionAttributes.getConcurrencyLevel());
regionFactory.setCustomEntryIdleTimeout(regionAttributes.getCustomEntryIdleTimeout());
regionFactory.setCustomEntryTimeToLive(regionAttributes.getCustomEntryTimeToLive());
regionFactory.setDiskSynchronous(regionAttributes.isDiskSynchronous());
regionFactory.setEnableAsyncConflation(regionAttributes.getEnableAsyncConflation());
regionFactory.setEnableSubscriptionConflation(regionAttributes.getEnableSubscriptionConflation());
regionFactory.setEntryIdleTimeout(regionAttributes.getEntryIdleTimeout());
regionFactory.setEntryTimeToLive(regionAttributes.getEntryTimeToLive());
// NOTE EvictionAttributes are created by certain RegionShortcuts; need the null check!
if (hasUserSpecifiedEvictionAttributes(regionAttributes)) {
regionFactory.setEvictionAttributes(regionAttributes.getEvictionAttributes());
}
regionFactory.setIgnoreJTA(regionAttributes.getIgnoreJTA());
regionFactory.setIndexMaintenanceSynchronous(regionAttributes.getIndexMaintenanceSynchronous());
regionFactory.setInitialCapacity(regionAttributes.getInitialCapacity());
regionFactory.setKeyConstraint(regionAttributes.getKeyConstraint());
regionFactory.setLoadFactor(regionAttributes.getLoadFactor());
regionFactory.setLockGrantor(regionAttributes.isLockGrantor());
regionFactory.setMembershipAttributes(regionAttributes.getMembershipAttributes());
regionFactory.setMulticastEnabled(regionAttributes.getMulticastEnabled());
mergePartitionAttributes(regionFactory, regionAttributes);
regionFactory.setPoolName(regionAttributes.getPoolName());
regionFactory.setRegionIdleTimeout(regionAttributes.getRegionIdleTimeout());
regionFactory.setRegionTimeToLive(regionAttributes.getRegionTimeToLive());
regionFactory.setStatisticsEnabled(regionAttributes.getStatisticsEnabled());
regionFactory.setSubscriptionAttributes(regionAttributes.getSubscriptionAttributes());
regionFactory.setValueConstraint(regionAttributes.getValueConstraint());
}
return regionFactory;
}
protected <K, V> void mergePartitionAttributes(final RegionFactory<K, V> regionFactory, final RegionAttributes<K, V> regionAttributes) {
// NOTE PartitionAttributes are created by certain RegionShortcuts; need the null check since RegionAttributes
// can technically return null!
// NOTE most likely, the PartitionAttributes will never be null since the PartitionRegionFactoryBean always
// sets a PartitionAttributesFactoryBean BeanBuilder on the RegionAttributesFactoryBean "partitionAttributes"
// property.
if (regionAttributes.getPartitionAttributes() != null) {
PartitionAttributes partitionAttributes = regionAttributes.getPartitionAttributes();
PartitionAttributesFactory partitionAttributesFactory = new PartitionAttributesFactory(partitionAttributes);
RegionShortcutWrapper shortcutWrapper = RegionShortcutWrapper.valueOf(shortcut);
// NOTE however, since the default value of redundancy is 0, we need to account for 'redundant'
// RegionShortcut types, which specify a redundancy of 1.
if (shortcutWrapper.isRedundant() && partitionAttributes.getRedundantCopies() == 0) {
partitionAttributesFactory.setRedundantCopies(1);
}
// NOTE and, since the default value of localMaxMemory is based on the system memory, we need to account for
// 'proxy' RegionShortcut types, which specify a local max memory of 0.
if (shortcutWrapper.isProxy()) {
partitionAttributesFactory.setLocalMaxMemory(0);
}
// NOTE internally, RegionFactory.setPartitionAttributes handles merging the PartitionAttributes, hooray!
regionFactory.setPartitionAttributes(partitionAttributesFactory.create());
}
}
/*
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
* NOTE unfortunately, must resort to using a GemFire internal class, ugh!
* @see com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes
*/
boolean hasUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) {
return (regionAttributes instanceof UserSpecifiedRegionAttributes
&& ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes());
}
/*
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
* @see com.gemstone.gemfire.cache.AttributesFactory#validateAttributes(:RegionAttributes)
*/
@SuppressWarnings("deprecation")
void validateRegionAttributes(final RegionAttributes regionAttributes) {
AttributesFactory.validateAttributes(regionAttributes);
}
/**
* Post-process the RegionFactory used to create the GemFire Region for this factory bean during the initialization
* process. The RegionFactory is already configured and initialized by the factory bean before this method
* is invoked.
* <p/>
* @param regionFactory the GemFire RegionFactory used to create the Region for post-processing.
* @see com.gemstone.gemfire.cache.RegionFactory
*/
protected void postProcess(RegionFactory<K, V> regionFactory) {
}
/**
* Post-process the Region for this factory bean during the initialization process. The Region is
* already configured and initialized by the factory bean before this method is invoked.
* <p/>
* @param region the GemFire Region to post-process.
* @see com.gemstone.gemfire.cache.Region
*/
protected void postProcess(Region<K, V> region) {
}
/**
* Validates and sets the Data Policy on the RegionFactory used to create and configure the Region from this
* FactoryBean.
* <p/>
* @param regionFactory the RegionFactory used by this FactoryBean to create and configure the Region.
* @param persistent a boolean value indicating whether the Region should be persistent and persist it's
* data to disk.
* @param dataPolicy the configured Data Policy for the Region.
* @see #resolveDataPolicy(com.gemstone.gemfire.cache.RegionFactory, Boolean, String)
* @see com.gemstone.gemfire.cache.DataPolicy
* @see com.gemstone.gemfire.cache.RegionFactory
*/
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy != null) {
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
regionFactory.setDataPolicy(dataPolicy);
}
else {
resolveDataPolicy(regionFactory, persistent, (String) null);
}
}
/**
* Validates the configured Data Policy and may override it, taking into account the 'persistent' attribute
* and constraints for the Region type.
* <p/>
* @param regionFactory the GemFire RegionFactory used to created the Local Region.
* @param persistent a boolean value indicating whether the Local Region should persist it's data.
* @param regionFactory the GemFire RegionFactory used to create the desired Region.
* @param persistent a boolean value indicating whether the Region should persist it's data to disk.
* @param dataPolicy requested Data Policy as set by the user in the Spring GemFire configuration meta-data.
* @see com.gemstone.gemfire.cache.DataPolicy
* @see com.gemstone.gemfire.cache.RegionFactory
@@ -220,40 +485,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
}
@SuppressWarnings("unchecked")
private AttributesFactory<K, V> findAttributesFactory(RegionFactory<K, V> regionFactory) {
Field attrsFactoryField = ReflectionUtils.findField(RegionFactory.class, "attrsFactory",
AttributesFactory.class);
ReflectionUtils.makeAccessible(attrsFactoryField);
return (AttributesFactory<K, V>) ReflectionUtils.getField(attrsFactoryField, regionFactory);
}
/**
* Post-process the attribute factory object used for configuring the region
* of this factory bean during the initialization process. The object is
* already initialized and configured by the factory bean before this method
* is invoked.
*
* @param attributesFactory attribute factory
* @deprecated as of GemFire 6.5, the use of {@link AttributesFactory} has
* been deprecated
*/
@Deprecated
@SuppressWarnings("unused")
protected void postProcess(AttributesFactory<K, V> attributesFactory) {
}
/**
* Post-process the region object for this factory bean during the
* initialization process. The object is already initialized and configured
* by the factory bean before this method is invoked.
*
* @param region
*/
@SuppressWarnings("unused")
protected void postProcess(Region<K, V> region) {
}
@Override
public void destroy() throws Exception {
if (getRegion() != null) {
@@ -274,9 +505,9 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
/**
*
* @param asyncEventQueues defined as Object for backward compatibility with
* Gemfire 6
* The list of AsyncEventQueues to use with this Region.
* <p/>
* @param asyncEventQueues defined as Object for backwards compatibility with Gemfire 6.
*/
public void setAsyncEventQueues(Object[] asyncEventQueues) {
this.asyncEventQueues = asyncEventQueues;
@@ -293,14 +524,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.attributes = attributes;
}
/**
* Indicates whether the region referred by this factory bean, will be
* closed on shutdown (default true).
*/
public void setClose(boolean close) {
this.close = close;
}
/**
* Sets the cache listeners used for the region used by this factory. Used
* only when a new region is created.Overrides the settings specified
@@ -334,6 +557,14 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.cacheWriter = cacheWriter;
}
/**
* Indicates whether the region referred by this factory bean, will be
* closed on shutdown (default true).
*/
public void setClose(boolean close) {
this.close = close;
}
/**
* Indicates whether the region referred by this factory bean, will be
* destroyed on shutdown (default false).
@@ -343,17 +574,30 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
/**
* Sets the dataPolicy as a String. Required to support property
* placeholders
* @param dataPolicyName the dataPolicy name (NORMAL, PRELOADED, etc)
* Sets the DataPolicy of the Region.
* <p/>
* @param dataPolicy the GemFire DataPolicy to use when configuring the Region.
* @since 1.4.0
*/
public void setDataPolicy(String dataPolicyName) {
this.dataPolicy = dataPolicyName;
public void setDataPolicy(DataPolicy dataPolicy) {
this.dataPolicy = dataPolicy;
}
/**
* Sets the name of disk store to use for overflow and persistence
* @param diskStoreName
* Sets the DataPolicy of the Region as a String.
* <p/>
* @param dataPolicyName the name of the DataPolicy (e.g. REPLICATE, PARTITION)
* @see #setDataPolicy(com.gemstone.gemfire.cache.DataPolicy)
* @deprecated as of 1.4.0, use setDataPolicy(:DataPolicy) instead.
*/
public void setDataPolicy(String dataPolicyName) {
this.dataPolicy = new DataPolicyConverter().convert(dataPolicyName);
}
/**
* Sets the name of Disk Store used for either overflow or persistence, or both.
* <p/>
* @param diskStoreName the name of the Disk Store bean in context used for overflow/persistence.
*/
public void setDiskStoreName(String diskStoreName) {
this.diskStoreName = diskStoreName;
@@ -376,7 +620,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.hubId = hubId;
}
public void setPersistent(boolean persistent) {
public void setPersistent(Boolean persistent) {
this.persistent = persistent;
}
@@ -391,6 +635,24 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.scope = scope;
}
/*
* (non-Javadoc)
*/
protected final RegionShortcut getShortcut() {
return shortcut;
}
/**
* Configures the Region with a RegionShortcut.
* <p/>
* @param shortcut the RegionShortcut used to configure pre-defined default for the Region created
* by this FactoryBean.
* @see com.gemstone.gemfire.cache.RegionShortcut
*/
public void setShortcut(RegionShortcut shortcut) {
this.shortcut = shortcut;
}
/**
* Sets the snapshots used for loading a newly <i>created</i> region. That
* is, the snapshot will be used <i>only</i> when a new region is created -
@@ -403,57 +665,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.snapshot = snapshot;
}
/**
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region/> elements
* are compatible.
* <p/>
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
* meta-data.
* @see #isPersistent()
* @see #isNotPersistent()
* @see com.gemstone.gemfire.cache.DataPolicy
*/
protected void assertDataPolicyAndPersistentAttributesAreCompatible(final DataPolicy resolvedDataPolicy) {
final boolean persistentNotSpecified = (this.persistent == null);
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(persistentNotSpecified || isPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
}
else {
// NOTE otherwise, the Data Policy is with persistence, so...
Assert.isTrue(persistentNotSpecified || isNotPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
}
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is true;
* false otherwise.
* @see #isNotPersistent()
*/
protected boolean isPersistent() {
return Boolean.TRUE.equals(persistent);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is false;
* false otherwise.
* @see #isPersistent()
*/
protected boolean isNotPersistent() {
return Boolean.FALSE.equals(persistent);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Lifecycle#start()
*/
@Override
@@ -461,9 +674,9 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (Object obj : gatewaySenders) {
GatewaySender gws = (GatewaySender) obj;
if (!(gws.isManualStart() || gws.isRunning())) {
gws.start();
GatewaySender gatewaySender = (GatewaySender) obj;
if (!(gatewaySender.isManualStart() || gatewaySender.isRunning())) {
gatewaySender.start();
}
}
}
@@ -471,22 +684,25 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.running = true;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Lifecycle#stop()
*/
@Override
public void stop() {
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (Object obj : gatewaySenders) {
((GatewaySender) obj).stop();
for (Object gatewaySender : gatewaySenders) {
((GatewaySender) gatewaySender).stop();
}
}
}
this.running = false;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Lifecycle#isRunning()
*/
@Override
@@ -494,7 +710,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return this.running;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Phased#getPhase()
*/
@Override
@@ -502,7 +719,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return Integer.MAX_VALUE;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
*/
@Override
@@ -510,7 +728,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return this.autoStartup;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
*/
@Override

View File

@@ -27,30 +27,36 @@ import com.gemstone.gemfire.cache.RegionFactory;
public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
if (dataPolicy != null) {
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
if (DataPolicy.EMPTY.equals(resolvedDataPolicy)) {
resolvedDataPolicy = DataPolicy.EMPTY;
}
else {
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:replicated-region .../>)!
Assert.isTrue(resolvedDataPolicy.withReplication(), String.format(
"Data Policy '%1$s' is not supported in Replicated Regions.", resolvedDataPolicy));
}
// Validate that the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
regionFactory.setDataPolicy(resolvedDataPolicy);
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy == null) {
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
}
else if (DataPolicy.EMPTY.equals(dataPolicy)) {
dataPolicy = DataPolicy.EMPTY;
}
else {
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for the Region (i.e. <gfe:replicated-region .../>)!
Assert.isTrue(dataPolicy.withReplication(), String.format(
"Data Policy '%1$s' is not supported in Replicated Regions.", dataPolicy));
}
// Validate that the data-policy and persistent attributes are compatible when both are specified!
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
regionFactory.setDataPolicy(dataPolicy);
}
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = null;
if (dataPolicy != null) {
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
}
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -80,7 +80,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "name");
ParsingUtils.setPropertyValue(element, builder, "data-policy");
ParsingUtils.setPropertyValue(element, builder, "persistent");
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "publisher");
ParsingUtils.setPropertyValue(element, builder, "shortcut");
if (StringUtils.hasText(element.getAttribute("disk-store-ref"))) {
ParsingUtils.setPropertyValue(element, builder, "disk-store-ref", "diskStoreName");
@@ -147,8 +147,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element,
new String[] { subElementName, subElementName + "-ref" });
List<Element> subElements = DomUtils.getChildElementsByTagName(element, subElementName,
subElementName + "-ref");
if (!CollectionUtils.isEmpty(subElements)) {
ManagedArray array = new ManagedArray(className, subElements.size());
@@ -224,4 +224,13 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
return parentPath;
}
protected void validateDataPolicyShortcutAttributesMutualExclusion(final Element element,
final ParserContext parserContext) {
if (element.hasAttribute("data-policy") && element.hasAttribute("shortcut")) {
parserContext.getReaderContext().error(String.format(
"Only one of [data-policy, shortcut] may be specified with element '%1$s'.", element.getTagName()),
element);
}
}
}

View File

@@ -49,7 +49,7 @@ class ClientRegionParser extends AbstractRegionParser {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutMutualExclusion(element, parserContext);
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
@@ -114,14 +114,6 @@ class ClientRegionParser extends AbstractRegionParser {
}
}
private void validateDataPolicyShortcutMutualExclusion(final Element element, final ParserContext parserContext) {
if (element.hasAttribute("data-policy") && element.hasAttribute("shortcut")) {
parserContext.getReaderContext().error(String.format(
"Only one of [data-policy, shortcut] may be specified with element '%1$s'.", element.getTagName()),
element);
}
}
private void parseDiskStoreAttribute(final Element element, final BeanDefinitionBuilder builder) {
String diskStoreRefAttribute = element.getAttribute("disk-store-ref");

View File

@@ -39,6 +39,8 @@ class LocalRegionParser extends AbstractRegionParser {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);

View File

@@ -303,6 +303,7 @@ abstract class ParsingUtils {
setPropertyValue(element, regionAttributesBuilder, "cloning-enabled");
setPropertyValue(element, regionAttributesBuilder, "concurrency-level");
setPropertyValue(element, regionAttributesBuilder, "disk-synchronous");
setPropertyValue(element, regionAttributesBuilder, "enable-async-conflation");
setPropertyValue(element, regionAttributesBuilder, "enable-subscription-conflation");
setPropertyValue(element, regionAttributesBuilder, "ignore-jta", "ignoreJTA");
@@ -311,6 +312,7 @@ abstract class ParsingUtils {
setPropertyValue(element, regionAttributesBuilder, "key-constraint");
setPropertyValue(element, regionAttributesBuilder, "load-factor");
setPropertyValue(element, regionAttributesBuilder, "multicast-enabled");
setPropertyValue(element, regionAttributesBuilder, "publisher");
setPropertyValue(element, regionAttributesBuilder, "value-constraint");
String indexUpdateType = element.getAttribute("index-update-type");

View File

@@ -46,10 +46,13 @@ class PartitionedRegionParser extends AbstractRegionParser {
return PartitionedRegionFactoryBean.class;
}
@SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
super.doParse(element, builder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
@@ -63,11 +66,11 @@ class PartitionedRegionParser extends AbstractRegionParser {
PartitionAttributesFactoryBean.class);
parseColocatedWith(element, builder, partitionAttributesBuilder, "colocated-with");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies","redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies", "redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "recovery-delay");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "startup-recovery-delay");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets","totalNumBuckets");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets", "totalNumBuckets");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-max-memory");
Element partitionResolverSubElement = DomUtils.getChildElementByTagName(element, "partition-resolver");

View File

@@ -40,13 +40,14 @@ class ReplicatedRegionParser extends AbstractRegionParser {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
ParsingUtils.parseScope(element, builder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder,
subRegion);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder, subRegion);
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
}

View File

@@ -129,8 +129,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
Object instance = instantiator.createInstance(entity, provider);
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper
.create(instance, conversionService);
final BeanWrapper<Object> wrapper = BeanWrapper.create(instance, conversionService);
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
@Override
@@ -168,7 +167,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
@Override
public boolean toData(Object value, final PdxWriter writer) {
GemfirePersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(value, conversionService);
final BeanWrapper<Object> wrapper = BeanWrapper.create(value, conversionService);
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
@SuppressWarnings({ "unchecked", "rawtypes" })

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2010-2013 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.support;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
/**
* The ClientRegionShortcutWrapper enum is a Java enumerated type that wraps GemFire's ClientRegionShortcuts
* with Spring Data GemFire ClientRegionShortcutWrapper enumerated values.
* <p/>
* @author John Blum
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
* @since 1.4.0
*/
@SuppressWarnings("unused")
public enum ClientRegionShortcutWrapper {
CACHING_PROXY(ClientRegionShortcut.CACHING_PROXY),
CACHING_PROXY_HEAP_LRU(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU),
CACHING_PROXY_OVERFLOW(ClientRegionShortcut.CACHING_PROXY_OVERFLOW),
LOCAL(ClientRegionShortcut.LOCAL),
LOCAL_HEAP_LRU(ClientRegionShortcut.LOCAL_HEAP_LRU),
LOCAL_OVERFLOW(ClientRegionShortcut.LOCAL_OVERFLOW),
LOCAL_PERSISTENT(ClientRegionShortcut.LOCAL_PERSISTENT),
LOCAL_PERSISTENT_OVERFLOW(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW),
PROXY(ClientRegionShortcut.PROXY),
UNSPECIFIED(null);
private final ClientRegionShortcut clientRegionShortcut;
ClientRegionShortcutWrapper(final ClientRegionShortcut clientRegionShortcut) {
this.clientRegionShortcut = clientRegionShortcut;
}
public static ClientRegionShortcutWrapper valueOf(final ClientRegionShortcut clientRegionShortcut) {
for (ClientRegionShortcutWrapper wrapper : values()) {
if (ObjectUtils.nullSafeEquals(wrapper.getClientRegionShortcut(), clientRegionShortcut)) {
return wrapper;
}
}
return ClientRegionShortcutWrapper.UNSPECIFIED;
}
public ClientRegionShortcut getClientRegionShortcut() {
return clientRegionShortcut;
}
public boolean isCaching() {
return name().contains("CACHING");
}
public boolean isHeapLru() {
return name().contains("HEAP_LRU");
}
public boolean isLocal() {
return name().contains("LOCAL");
}
public boolean isOverflow() {
return name().contains("OVERFLOW");
}
public boolean isPersistent() {
return name().contains("PERSISTENT");
}
public boolean isPersistentOverflow() {
return name().contains("PERSISTENT_OVERFLOW");
}
public boolean isProxy() {
return name().contains("PROXY");
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2010-2013 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.support;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.RegionShortcut;
/**
* The RegionShortcutWrapper enum is a Java enumerated type that wraps GemFire's RegionShortcuts
* with Spring Data GemFire RegionShortcutWrapper enumerated values.
* <p/>
*
* @author John Blum
* @see com.gemstone.gemfire.cache.RegionShortcut
* @since 1.4.0
*/
@SuppressWarnings("unused")
public enum RegionShortcutWrapper {
LOCAL(RegionShortcut.LOCAL),
LOCAL_HEAP_LRU(RegionShortcut.LOCAL_HEAP_LRU),
LOCAL_OVERFLOW(RegionShortcut.LOCAL_OVERFLOW),
LOCAL_PERSISTENT(RegionShortcut.LOCAL_PERSISTENT),
LOCAL_PERSISTENT_OVERFLOW(RegionShortcut.LOCAL_PERSISTENT_OVERFLOW),
PARTITION(RegionShortcut.PARTITION),
PARTITION_HEAP_LRU(RegionShortcut.PARTITION_HEAP_LRU),
PARTITION_OVERFLOW(RegionShortcut.PARTITION_OVERFLOW),
PARTITION_PERSISTENT(RegionShortcut.PARTITION_PERSISTENT),
PARTITION_PERSISTENT_OVERFLOW(RegionShortcut.PARTITION_PERSISTENT_OVERFLOW),
PARTITION_PROXY(RegionShortcut.PARTITION_PROXY),
PARTITION_PROXY_REDUNDANT(RegionShortcut.PARTITION_PROXY_REDUNDANT),
PARTITION_REDUNDANT(RegionShortcut.PARTITION_REDUNDANT),
PARTITION_REDUNDANT_HEAP_LRU(RegionShortcut.PARTITION_REDUNDANT_HEAP_LRU),
PARTITION_REDUNDANT_OVERFLOW(RegionShortcut.PARTITION_REDUNDANT_OVERFLOW),
PARTITION_REDUNDANT_PERSISTENT(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT),
PARTITION_REDUNDANT_PERSISTENT_OVERFLOW(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW),
REPLICATE(RegionShortcut.REPLICATE),
REPLICATE_HEAP_LRU(RegionShortcut.REPLICATE_HEAP_LRU),
REPLICATE_OVERFLOW(RegionShortcut.REPLICATE_OVERFLOW),
REPLICATE_PERSISTENT(RegionShortcut.REPLICATE_PERSISTENT),
REPLICATE_PERSISTENT_OVERFLOW(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW),
REPLICATE_PROXY(RegionShortcut.REPLICATE_PROXY),
UNSPECIFIED(null);
private final RegionShortcut regionShortcut;
RegionShortcutWrapper(final RegionShortcut regionShortcut) {
this.regionShortcut = regionShortcut;
}
public static RegionShortcutWrapper valueOf(final RegionShortcut regionShortcut) {
for (RegionShortcutWrapper wrapper : values()) {
if (ObjectUtils.nullSafeEquals(wrapper.getRegionShortcut(), regionShortcut)) {
return wrapper;
}
}
return RegionShortcutWrapper.UNSPECIFIED;
}
public boolean isHeapLru() {
return name().contains("HEAP_LRU");
}
public boolean isLocal() {
return name().contains("LOCAL");
}
public boolean isOverflow() {
return name().contains("OVERFLOW");
}
public boolean isPartition() {
return name().contains("PARTITION");
}
public boolean isPersistent() {
return name().contains("PERSISTENT");
}
public boolean isPersistentOverflow() {
return (isOverflow() && isPersistent());
}
public boolean isProxy() {
return name().contains("PROXY");
}
public boolean isRedundant() {
return name().contains("REDUNDANT");
}
public boolean isReplicate() {
return name().contains("REPLICATE");
}
public RegionShortcut getRegionShortcut() {
return regionShortcut;
}
}

View File

@@ -2,7 +2,7 @@ http\://www.springframework.org/schema/gemfire/spring-gemfire-1.0.xsd=org/spring
http\://www.springframework.org/schema/gemfire/spring-gemfire-1.1.xsd=org/springframework/data/gemfire/config/spring-gemfire-1.1.xsd
http\://www.springframework.org/schema/gemfire/spring-gemfire-1.2.xsd=org/springframework/data/gemfire/config/spring-gemfire-1.2.xsd
http\://www.springframework.org/schema/gemfire/spring-gemfire-1.3.xsd=org/springframework/data/gemfire/config/spring-gemfire-1.3.xsd
http\://www.springframework.org/schema/gemfire/spring-gemfire-1.3.xsd=org/springframework/data/gemfire/config/spring-gemfire-1.4.xsd
http\://www.springframework.org/schema/gemfire/spring-gemfire-1.4.xsd=org/springframework/data/gemfire/config/spring-gemfire-1.4.xsd
http\://www.springframework.org/schema/gemfire/spring-gemfire.xsd=org/springframework/data/gemfire/config/spring-gemfire-1.4.xsd
http\://www.springframework.org/schema/data/gemfire/spring-data-gemfire-1.2.xsd=org/springframework/data/gemfire/config/spring-data-gemfire-1.2.xsd
http\://www.springframework.org/schema/data/gemfire/spring-data-gemfire-1.3.xsd=org/springframework/data/gemfire/config/spring-data-gemfire-1.3.xsd

View File

@@ -1,14 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.org/schema/gemfire"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool" xmlns:context="http://www.springframework.org/schema/context"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:repository="http://www.springframework.org/schema/data/repository"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.springframework.org/schema/gemfire"
elementFormDefault="qualified" attributeFormDefault="unqualified"
version="1.4">
<xsd:import namespace="http://www.springframework.org/schema/beans" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<xsd:import namespace="http://www.springframework.org/schema/context" />
<xsd:import namespace="http://www.springframework.org/schema/tool" />
<!-- -->
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -998,6 +1000,28 @@ reduce thread contention. This sets an initial parameter on the underlying java.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="data-policy" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the data policy for this region (EMPTY, REPLICATE, PERSISTENT_REPLICATE). Setting 'data-policy' is not
stictly necessary, but if set, then the value must agree with the 'persistent' attribute if also specified.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="EMPTY"/>
<xsd:enumeration value="REPLICATE"/>
<xsd:enumeration value="PERSISTENT_REPLICATE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="is-lock-grantor" type="xsd:string" use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether the region is a lock grantor.This attribute is only relevant for regions with global scope, as only they allow locking.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="scope" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -1005,20 +1029,22 @@ Specifies the scope for this region: distributed-ack,distributed-no-ack, global
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="data-policy" type="xsd:string">
<xsd:attribute name="shortcut" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the data policy for this region
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="is-lock-grantor" type="xsd:string"
use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether the region is a lock grantor.This attribute is only relevant for regions with global scope, as only they allow locking.
]]></xsd:documentation>
The RegionShortcut for this region. Allows easy initialization of the region based on pre-defined defaults.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="REPLICATE"/>
<xsd:enumeration value="REPLICATE_PERSISTENT"/>
<xsd:enumeration value="REPLICATE_OVERFLOW"/>
<xsd:enumeration value="REPLICATE_PERSISTENT_OVERFLOW"/>
<xsd:enumeration value="REPLICATE_HEAP_LRU"/>
<xsd:enumeration value="REPLICATE_PROXY"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
@@ -1086,13 +1112,6 @@ The action to take when performing eviction.
</xsd:element>
<xsd:group ref="subRegionGroup" minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="data-policy" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates the DataPolicy to use for this region (NORMAL or PRELOADED)
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="concurrency-level">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -1102,6 +1121,36 @@ reduce thread contention. This sets an initial parameter on the underlying java.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="data-policy" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the data policy for this region (NORMAL or PRELOADED). Setting 'data-policy' is not stictly necessary,
but if set, then the value must agree with the 'persistent' attribute if also specified.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="NORMAL"/>
<xsd:enumeration value="PRELOADED"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="shortcut" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The RegionShortcut for this region. Allows easy initialization of the region based on pre-defined defaults.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="LOCAL"/>
<xsd:enumeration value="LOCAL_PERSISTENT"/>
<xsd:enumeration value="LOCAL_HEAP_LRU"/>
<xsd:enumeration value="LOCAL_OVERFLOW"/>
<xsd:enumeration value="LOCAL_PERSISTENT_OVERFLOW"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -1257,16 +1306,28 @@ redundancy. Each copy provides extra backup at the expense of extra storages.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="colocated-with" type="xsd:string"
use="optional">
<xsd:attribute name="colocated-with" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The name of the partitioned region with which this newly created partitioned region is colocated.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="local-max-memory" type="xsd:string"
use="optional">
<xsd:attribute name="data-policy" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Specifies the data policy for this region (PARTITION, PERSISTENT_PARTITION). Setting 'data-policy' is not
stictly necessary, but if set, then the value must agree with the 'persistent' attribute if also specified.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="PARTITION"/>
<xsd:enumeration value="PERSISTENT_PARTITION"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="local-max-memory" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum amount of memory, in megabytes, to be used by the region in this process. If not set, a default of 90%
@@ -1274,18 +1335,16 @@ of available heap is used.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="total-max-memory" type="xsd:string"
use="optional">
<xsd:attribute name="total-max-memory" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum amount of memory, in megabytes, to be used by the region in all process.
Note: This setting must be the same in all processes using the region.
]]></xsd:documentation>
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="total-buckets" type="xsd:string"
use="optional">
<xsd:attribute name="total-buckets" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The total number of hash buckets to be used by the region in all processes.
@@ -1300,8 +1359,7 @@ Note: This setting must be the same in all processes using the region.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="recovery-delay" type="xsd:string"
use="optional" default="-1">
<xsd:attribute name="recovery-delay" type="xsd:string" use="optional" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The delay in milliseconds that existing members will wait before satisfying redundancy after another member crashes.
@@ -1309,8 +1367,30 @@ The delay in milliseconds that existing members will wait before satisfying redu
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="startup-recovery-delay" type="xsd:string"
use="optional" default="-1">
<xsd:attribute name="shortcut" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The RegionShortcut for this region. Allows easy initialization of the region based on pre-defined defaults.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="PARTITION"/>
<xsd:enumeration value="PARTITION_REDUNDANT"/>
<xsd:enumeration value="PARTITION_PERSISTENT"/>
<xsd:enumeration value="PARTITION_REDUNDANT_PERSISTENT"/>
<xsd:enumeration value="PARTITION_OVERFLOW"/>
<xsd:enumeration value="PARTITION_REDUNDANT_OVERFLOW"/>
<xsd:enumeration value="PARTITION_PERSISTENT_OVERFLOW"/>
<xsd:enumeration value="PARTITION_REDUNDANT_PERSISTENT_OVERFLOW"/>
<xsd:enumeration value="PARTITION_HEAP_LRU"/>
<xsd:enumeration value="PARTITION_REDUNDANT_HEAP_LRU"/>
<xsd:enumeration value="PARTITION_PROXY"/>
<xsd:enumeration value="PARTITION_PROXY_REDUNDANT"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="startup-recovery-delay" type="xsd:string" use="optional" default="-1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The delay in milliseconds that new members will wait before satisfying redundancy. -1 indicates that adding new members
@@ -1745,21 +1825,27 @@ The action to take when performing eviction.
</xsd:element>
<xsd:group ref="subRegionGroup" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="data-policy" type="xsd:string"
use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The data policy for this client. Can be either 'EMPTY' or 'NORMAL' (the default). In case persistence or overflow are
configured for this region, this parameter will be ignored.
<xsd:attribute name="data-policy" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The data policy for this client region. Can be either 'EMPTY' or 'NORMAL' (the default). In case persistence or overflow
are configured for this region, this parameter will be ignored.
EMPTY - causes data to never be stored in local memory. The region will always appear empty. It can be used for zero
footprint producers that only want to distribute their data to others and for zero footprint consumers that only want
to see events.
EMPTY - causes data to never be stored in local memory. The region will always appear empty. It can be used to for zero
footprint producers that only want to distribute their data to others and for zero footprint consumers that only want
to see events.
NORMAL - causes data that this region is interested in to be stored in local memory. It allows the contents in this
cache to differ from other caches.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="EMPTY"/>
<xsd:enumeration value="NORMAL"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="pool-name" type="xsd:string"
use="optional">
<xsd:annotation>
@@ -1771,20 +1857,20 @@ The name of the pool used by this client. If not set, a default pool (initialize
<xsd:attribute name="shortcut" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The ClientRegionShortcut for this region. Allows easy initialization of the region based on defaults.
The ClientRegionShortcut for this region. Allows easy initialization of the region based on pre-defined defaults.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="PROXY" />
<xsd:enumeration value="CACHING_PROXY" />
<xsd:enumeration value="CACHING_PROXY_HEAP_LRU" />
<xsd:enumeration value="CACHING_PROXY_OVERFLOW" />
<xsd:enumeration value="LOCAL" />
<xsd:enumeration value="LOCAL_PERSISTENT" />
<xsd:enumeration value="LOCAL_HEAP_LRU" />
<xsd:enumeration value="LOCAL_OVERFLOW" />
<xsd:enumeration value="LOCAL_PERSISTENT_OVERFLOW" />
<xsd:enumeration value="PROXY"/>
<xsd:enumeration value="CACHING_PROXY"/>
<xsd:enumeration value="CACHING_PROXY_HEAP_LRU"/>
<xsd:enumeration value="CACHING_PROXY_OVERFLOW"/>
<xsd:enumeration value="LOCAL"/>
<xsd:enumeration value="LOCAL_PERSISTENT"/>
<xsd:enumeration value="LOCAL_HEAP_LRU"/>
<xsd:enumeration value="LOCAL_OVERFLOW"/>
<xsd:enumeration value="LOCAL_PERSISTENT_OVERFLOW"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>