Additional work and changes for JIRA feature requests SGF-207 and SGF-254 to enable developers with the ability to create Region templates to model attributes and configuration meta-data common to multiple, strongly-typed GemFire Region types (e.g. REPLICATE, PARTITION, etc).

This commit is contained in:
John Blum
2014-08-22 13:11:30 -07:00
committed by John Blum
parent 5d27c19ef5
commit 2f66eca99b
5 changed files with 209 additions and 32 deletions

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -29,6 +30,7 @@ import org.springframework.beans.factory.support.ManagedArray;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
@@ -81,6 +83,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
protected void doParseCommonRegionConfiguration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, BeanDefinitionBuilder regionAttributesBuilder, boolean subRegion) {
mergeTemplateRegionAttributes(element, parserContext, builder, regionAttributesBuilder);
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
if (!subRegion) {
@@ -159,6 +163,45 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
}
}
void mergeTemplateRegionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionBuilder, BeanDefinitionBuilder regionAttributesBuilder) {
String regionTemplate = getParentName(element);
if (StringUtils.hasText(regionTemplate)) {
if (parserContext.getRegistry().containsBeanDefinition(regionTemplate)) {
BeanDefinition regionTemplateDefinition = parserContext.getRegistry()
.getBeanDefinition(regionTemplate);
BeanDefinition regionTemplateAttributesDefinition = getRegionAttributesBeanDefinition(
regionTemplateDefinition);
if (regionTemplateAttributesDefinition != null) {
// NOTE we only need to merge the parent RegionAttributes with this since the parent will have
// already merged it's parent's RegionAttributes and so on...
regionAttributesBuilder.getRawBeanDefinition().overrideFrom(regionTemplateAttributesDefinition);
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be defined in the Spring context configuration meta-data 'before' the Region [%2$s] using the template!",
regionTemplate, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)), element);
}
}
}
BeanDefinition getRegionAttributesBeanDefinition(final BeanDefinition region) {
Assert.notNull(region, "The 'Region' BeanDefinition must not be null!");
Object regionAttributesDefinition = null;
if (region.getPropertyValues().contains("attributes")) {
PropertyValue regionAttributes = region.getPropertyValues().getPropertyValue("attributes");
regionAttributesDefinition = regionAttributes.getValue();
}
return (regionAttributesDefinition instanceof BeanDefinition ? (BeanDefinition) regionAttributesDefinition : null);
}
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element, subElementName,

View File

@@ -18,6 +18,8 @@ package org.springframework.data.gemfire.config;
import java.util.List;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
@@ -53,8 +55,6 @@ class PartitionedRegionParser extends AbstractRegionParser {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
super.doParse(element, regionBuilder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
@@ -65,6 +65,8 @@ class PartitionedRegionParser extends AbstractRegionParser {
BeanDefinitionBuilder partitionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
PartitionAttributesFactoryBean.class);
mergeTemplateRegionPartitionAttributes(element, parserContext, regionBuilder, partitionAttributesBuilder);
parseColocatedWith(element, regionBuilder, partitionAttributesBuilder, "colocated-with");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies", "redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
@@ -108,6 +110,40 @@ class PartitionedRegionParser extends AbstractRegionParser {
regionAttributesBuilder.addPropertyValue("partitionAttributes", partitionAttributesBuilder.getBeanDefinition());
}
void mergeTemplateRegionPartitionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionBuilder, BeanDefinitionBuilder partitionAttributesBuilder) {
String regionTemplate = getParentName(element);
if (StringUtils.hasText(regionTemplate)) {
if (parserContext.getRegistry().containsBeanDefinition(regionTemplate)) {
BeanDefinition regionTemplateDefinition = parserContext.getRegistry()
.getBeanDefinition(regionTemplate);
BeanDefinition regionTemplateAttributesDefinition = getRegionAttributesBeanDefinition(
regionTemplateDefinition);
if (regionTemplateAttributesDefinition != null) {
if (regionTemplateAttributesDefinition.getPropertyValues().contains("partitionAttributes")) {
PropertyValue partitionAttributes = regionTemplateAttributesDefinition.getPropertyValues()
.getPropertyValue("partitionAttributes");
Object partitionAttributesDefinition = partitionAttributes.getValue();
if (partitionAttributesDefinition instanceof BeanDefinition) {
partitionAttributesBuilder.getRawBeanDefinition().overrideFrom(
(BeanDefinition) partitionAttributesDefinition);
}
}
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be defined in the Spring context configuration meta-data 'before' the Region [%2$s] using the template!",
regionTemplate, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)), element);
}
}
}
private void parseColocatedWith(Element element, BeanDefinitionBuilder regionBuilder,
BeanDefinitionBuilder partitionAttributesBuilder, String attributeName) {
// NOTE rather than using a dependency (with depends-on) we could also set the colocatedWith property of the

View File

@@ -123,8 +123,7 @@ Configures a data source to be bound to a JNDI context for use with Gemfire tran
The name of the cache definition (by default "gemfireCache").]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-xml-location" type="xsd:string"
use="optional">
<xsd:attribute name="cache-xml-location" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="org.springframework.core.io.Resource"><![CDATA[
The location of the GemFire cache xml file, as a Spring resource location: a URL, a "classpath:" pseudo URL,
@@ -132,8 +131,7 @@ or a relative file path.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="properties-ref" type="xsd:string"
use="optional">
<xsd:attribute name="properties-ref" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation source="java.util.Properties"><![CDATA[
The bean name of a Java Properties object that will be used for property substitution. For loading properties
@@ -149,8 +147,7 @@ For cases in which there are no declared dependencies on the cache, set this att
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="use-bean-factory-locator" type="xsd:string"
use="optional" default="true">
<xsd:attribute name="use-bean-factory-locator" type="xsd:string" use="optional" default="true">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether a bean factory locator is enabled (default) for this cache definition or not. The locator stores
@@ -168,8 +165,7 @@ same cache instance.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="copy-on-read" type="xsd:string"
use="optional" default="false">
<xsd:attribute name="copy-on-read" type="xsd:string" use="optional" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether entry value retrieval methods return direct references to the entry value objects in the cache (false)
@@ -198,8 +194,7 @@ JavaDocs for com.gemstone.gemfire.cache.control.ResourceManager for more informa
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-serializer-ref" type="xsd:string"
use="optional">
<xsd:attribute name="pdx-serializer-ref" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the PDX serializer for the cache. If this serializer is set, it will be consulted to see if it can serialize any
@@ -207,8 +202,7 @@ domain classes which are added to the cache in portable data exchange (PDX) form
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-persistent" type="xsd:string"
use="optional">
<xsd:attribute name="pdx-persistent" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Control whether the type metadata for PDX objects is persisted to disk.
@@ -216,8 +210,7 @@ Set to true if you are using persistent regions, WAN gateways or GemFire's JSON
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-disk-store" type="xsd:string"
use="optional">
<xsd:attribute name="pdx-disk-store" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the name of the disk store to use for PDX meta data. When serializing objects in the PDX format,
@@ -226,8 +219,7 @@ If not set, the metadata will go in the default disk store.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-read-serialized" type="xsd:string"
use="optional">
<xsd:attribute name="pdx-read-serialized" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Sets the object preference to PdxInstance type. When a cached object that was serialized as a PDX is read from the cache
@@ -241,8 +233,7 @@ then a domain class instance is returned instead of a PdxInstance.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pdx-ignore-unread-fields" type="xsd:string"
use="optional">
<xsd:attribute name="pdx-ignore-unread-fields" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls whether pdx ignores fields that were unread during deserialization. The default is to preserve unread fields be

View File

@@ -19,11 +19,11 @@ package org.springframework.data.gemfire.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
@@ -33,18 +33,24 @@ import org.springframework.beans.factory.BeanIsAbstractException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.test.GemfireTestApplicationContextInitializer;
import org.springframework.data.gemfire.test.support.CollectionUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheLoaderException;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EntryOperation;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAlgorithm;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.InterestPolicy;
import com.gemstone.gemfire.cache.LoaderHelper;
import com.gemstone.gemfire.cache.PartitionResolver;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.SubscriptionAttributes;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEvent;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventListener;
import com.gemstone.gemfire.cache.partition.PartitionListenerAdapter;
@@ -73,6 +79,25 @@ public class TemplateRegionsNamespaceTests {
@Resource(name = "SimpleReplicateRegion")
private Region<Integer, String> simpleReplicateRegion;
@Resource(name = "InheritedReplicateRegion")
private Region<Long, String> inheritedReplicateRegion;
@Resource(name = "ComplexReplicateRegion")
private Region complexReplicateRegion;
protected static void assertRegionMetaData(final Region<?, ?> region, final String expectedRegionName) {
assertRegionMetaData(region, expectedRegionName, Region.SEPARATOR + expectedRegionName);
}
protected static void assertRegionMetaData(final Region<?, ?> region, final String expectedRegionName, final String expectedRegionPath) {
assertNotNull(String.format("The '%1$s' Region was not properly configured and initialized!",
expectedRegionName), region);
assertEquals(expectedRegionName, region.getName());
assertEquals(expectedRegionPath, region.getFullPath());
assertNotNull(String.format("The '%1$s' Region must have RegionAttributes defined!",
expectedRegionName), region.getAttributes());
}
@SuppressWarnings("deprecation")
protected static <K, V> void assertBaseRegionAttributes(final Region<K, V> region) {
assertNotNull("The Region must not be null!", region);
@@ -100,6 +125,25 @@ public class TemplateRegionsNamespaceTests {
assertEquals("Y", regionAttributes.getCacheWriter().toString());
}
protected static <K, V> void assertBaseReplicateRegionAttributes(final Region<K, V> replicateRegion) {
assertBaseRegionAttributes(replicateRegion);
assertEquals(2, replicateRegion.getAttributes().getConcurrencyLevel());
assertTrue(replicateRegion.getAttributes().getEnableAsyncConflation());
assertTrue(replicateRegion.getAttributes().getEnableSubscriptionConflation());
EvictionAttributes evictionAttributes = replicateRegion.getAttributes().getEvictionAttributes();
assertNotNull(evictionAttributes);
assertEquals(EvictionAction.OVERFLOW_TO_DISK, evictionAttributes.getAction());
assertEquals(EvictionAlgorithm.LRU_ENTRY, evictionAttributes.getAlgorithm());
assertEquals(1000, evictionAttributes.getMaximum());
SubscriptionAttributes subscriptionAttributes = replicateRegion.getAttributes().getSubscriptionAttributes();
assertNotNull(subscriptionAttributes);
assertEquals(InterestPolicy.CACHE_CONTENT, subscriptionAttributes.getInterestPolicy());
}
@Test
public void testNoAbstractRegionTemplateBeans() {
String[] beanNames = {
@@ -124,7 +168,66 @@ public class TemplateRegionsNamespaceTests {
@Test
public void testSimpleReplicateRegion() {
fail("Not Implemented!");
assertRegionMetaData(simpleReplicateRegion, "SimpleReplicateRegion");
assertEquals(DataPolicy.PERSISTENT_REPLICATE, simpleReplicateRegion.getAttributes().getDataPolicy());
assertEquals(8, simpleReplicateRegion.getAttributes().getConcurrencyLevel());
assertEquals(Integer.class, simpleReplicateRegion.getAttributes().getKeyConstraint());
assertTrue(simpleReplicateRegion.getAttributes().isLockGrantor());
assertEquals(Scope.GLOBAL, simpleReplicateRegion.getAttributes().getScope());
assertNull(simpleReplicateRegion.getAttributes().getValueConstraint());
assertNotNull(simpleReplicateRegion.getAttributes().getCacheListeners());
assertEquals(1, simpleReplicateRegion.getAttributes().getCacheListeners().length);
assertTrue(simpleReplicateRegion.getAttributes().getCacheListeners()[0] instanceof TestCacheListener);
assertEquals("Simple", simpleReplicateRegion.getAttributes().getCacheListeners()[0].toString());
assertNull(simpleReplicateRegion.getAttributes().getCacheLoader());
assertNull(simpleReplicateRegion.getAttributes().getCacheWriter());
}
@Test
public void testInheritedReplicateRegion() {
assertRegionMetaData(inheritedReplicateRegion, "InheritedReplicateRegion");
assertEquals(Scope.DISTRIBUTED_ACK, inheritedReplicateRegion.getAttributes().getScope());
assertBaseReplicateRegionAttributes(inheritedReplicateRegion);
}
@Test
@SuppressWarnings("deprecation")
public void testComplexReplicateRegion() {
assertRegionMetaData(complexReplicateRegion, "ComplexReplicateRegion");
assertEquals(DataPolicy.PERSISTENT_REPLICATE, complexReplicateRegion.getAttributes().getDataPolicy());
assertEquals(Scope.DISTRIBUTED_ACK, complexReplicateRegion.getAttributes().getScope());
assertFalse(complexReplicateRegion.getAttributes().getCloningEnabled());
assertEquals(2, complexReplicateRegion.getAttributes().getConcurrencyLevel());
assertTrue(complexReplicateRegion.getAttributes().isDiskSynchronous());
assertFalse(complexReplicateRegion.getAttributes().getEnableAsyncConflation());
assertTrue(complexReplicateRegion.getAttributes().getEnableSubscriptionConflation());
assertFalse(complexReplicateRegion.getAttributes().getIgnoreJTA());
assertEquals(1000, complexReplicateRegion.getAttributes().getInitialCapacity());
assertEquals(Integer.class, complexReplicateRegion.getAttributes().getKeyConstraint());
assertEquals(0.90f, complexReplicateRegion.getAttributes().getLoadFactor());
assertTrue(complexReplicateRegion.getAttributes().getStatisticsEnabled());
assertTrue(complexReplicateRegion.getAttributes().getIndexMaintenanceSynchronous());
assertEquals(String.class, complexReplicateRegion.getAttributes().getValueConstraint());
assertNotNull(complexReplicateRegion.getAttributes().getCacheListeners());
assertEquals(1, complexReplicateRegion.getAttributes().getCacheListeners().length);
assertTrue(complexReplicateRegion.getAttributes().getCacheListeners()[0] instanceof TestCacheListener);
assertEquals("ComplexListener", complexReplicateRegion.getAttributes().getCacheListeners()[0].toString());
assertNotNull(complexReplicateRegion.getAttributes().getCacheLoader());
assertEquals("ComplexLoader", complexReplicateRegion.getAttributes().getCacheLoader().toString());
assertNotNull(complexReplicateRegion.getAttributes().getCacheWriter());
assertEquals("Y", complexReplicateRegion.getAttributes().getCacheWriter().toString());
EvictionAttributes evictionAttributes = complexReplicateRegion.getAttributes().getEvictionAttributes();
assertNotNull(evictionAttributes);
assertEquals(EvictionAction.OVERFLOW_TO_DISK, evictionAttributes.getAction());
assertEquals(EvictionAlgorithm.LRU_ENTRY, evictionAttributes.getAlgorithm());
assertEquals(1024, evictionAttributes.getMaximum());
SubscriptionAttributes subscriptionAttributes = complexReplicateRegion.getAttributes().getSubscriptionAttributes();
assertNotNull(subscriptionAttributes);
assertEquals(InterestPolicy.ALL, subscriptionAttributes.getInterestPolicy());
}
protected static interface Nameable {

View File

@@ -19,7 +19,7 @@
<gfe:gateway-sender id="TestGatewaySender" remote-distributed-system-id="123" manual-start="true" persistent="false"
parallel="true" dispatcher-threads="8"/>
<!-- Generic Region -->
<!-- Region Templates -->
<gfe:region-template id="BaseRegion" cloning-enabled="true" concurrency-checks-enabled="false"
disk-synchronous="true" ignore-jta="true" initial-capacity="1000"
@@ -34,7 +34,8 @@
</gfe:region-template>
<gfe:region-template id="ExtendedRegionWithOverrides" cloning-enabled="false" concurrency-checks-enabled="true"
disk-synchronous="false" ignore-jta="false" key-constraint="java.lang.String" template="BaseRegion">
disk-synchronous="false" ignore-jta="false" key-constraint="java.lang.String" persistent="false"
template="BaseRegion">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="Z"/>
</gfe:cache-listener>
@@ -45,7 +46,7 @@
<!-- REPLICATE Region -->
<gfe:replicated-region-template id="BaseReplicateRegion" concurrency-level="2" enable-async-conflation="true"
enable-subscription-conflation="true" template="BaseRegion">
enable-subscription-conflation="true" scope="global" template="BaseRegion">
<gfe:subscription type="CACHE_CONTENT"/>
<gfe:eviction type="ENTRY_COUNT" threshold="1000" action="OVERFLOW_TO_DISK"/>
</gfe:replicated-region-template>
@@ -53,19 +54,19 @@
<gfe:replicated-region id="SimpleReplicateRegion" persistent="true" concurrency-level="8" is-lock-grantor="true" scope="global"
key-constraint="java.lang.Integer">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="A"/>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="Simple"/>
</gfe:cache-listener>
</gfe:replicated-region>
<gfe:replicated-region id="InheritedReplicateRegion" template="BaseReplicateRegion"/>
<gfe:replicated-region id="ComplexReplicateRegion" persistent="true" key-constraint="java.lang.Integer" cloning-enabled="false"
template="BaseReplicateRegion">
<gfe:replicated-region id="ComplexReplicateRegion" persistent="true" key-constraint="java.lang.Integer" ignore-jta="false"
enable-async-conflation="false" cloning-enabled="false" template="BaseReplicateRegion">
<gfe:cache-listener>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="AAA"/>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheListener" p:name="ComplexListener"/>
</gfe:cache-listener>
<gfe:cache-loader>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheLoader" p:name="xyz"/>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestCacheLoader" p:name="ComplexLoader"/>
</gfe:cache-loader>
<gfe:subscription type="ALL"/>
<gfe:eviction type="ENTRY_COUNT" threshold="1024" action="OVERFLOW_TO_DISK"/>
@@ -74,7 +75,8 @@
<!-- PARTITION Region -->
<gfe:partitioned-region-template id="BasePartitionRegion" copies="2" local-max-memory="1000" total-max-memory="4000"
total-buckets="77" recovery-delay="1000" startup-recovery-delay="5000">
total-buckets="77" recovery-delay="1000" startup-recovery-delay="5000"
template="ExtendedRegionWithOverrides">
<gfe:partition-resolver>
<bean class="org.springframework.data.gemfire.config.TemplateRegionsNamespaceTests$TestPartitionResolver" p:name="A"/>
</gfe:partition-resolver>
@@ -85,6 +87,8 @@
<gfe:eviction type="MEMORY_SIZE" threshold="4000" action="OVERFLOW_TO_DISK"/>
</gfe:partitioned-region-template>
<!-- LOCAL Region -->
<gfe:local-region-template id="BaseLocalRegion" concurrency-level="4">
<gfe:eviction type="ENTRY_COUNT" threshold="8192" action="LOCAL_DESTROY"/>
</gfe:local-region-template>