+ add persistence and overflow support for client regions
This commit is contained in:
Costin Leau
2010-10-31 17:34:17 +02:00
parent ef9dbdf2f9
commit 1ba1cfa32c
5 changed files with 139 additions and 27 deletions

View File

@@ -17,11 +17,13 @@
package org.springframework.data.gemfire.config;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.RegionAttributesFactory;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.client.Interest;
import org.springframework.data.gemfire.client.RegexInterest;
@@ -29,6 +31,9 @@ import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.Scope;
/**
@@ -59,10 +64,42 @@ class ClientRegionParser extends AbstractSingleBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "name", "name");
ParsingUtils.setPropertyValue(element, builder, "pool-name", "poolName");
String attr = element.getAttribute("cache-ref");
// set the persistent policy
String attr = element.getAttribute("persistent");
boolean frozenDataPolicy = false;
if (Boolean.parseBoolean(attr)) {
// check first for GemFire 6.5
if (ConcurrentMap.class.isAssignableFrom(Region.class)) {
builder.addPropertyValue("dataPolicy", DataPolicy.PERSISTENT_REPLICATE);
frozenDataPolicy = true;
}
else {
parserContext.getReaderContext().error(
"Can define persistent partitions only from GemFire 6.5 onwards - current version is ["
+ CacheFactory.getVersion() + "]", element);
}
}
attr = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified)
builder.addPropertyReference("cache", (StringUtils.hasText(attr) ? attr : "gemfire-cache"));
// eviction + overflow attributes
// client attributes
BeanDefinitionBuilder attrBuilder = BeanDefinitionBuilder.genericBeanDefinition(RegionAttributesFactory.class);
ParsingUtils.parseEviction(parserContext, element, attrBuilder);
ParsingUtils.parseDiskStorage(element, attrBuilder);
if (!frozenDataPolicy) {
builder.addPropertyValue("dataPolicy", DataPolicy.NORMAL);
}
// add partition/overflow settings as attributes
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
ManagedList<Object> interests = new ManagedList<Object>();
// parse nested declarations

View File

@@ -148,7 +148,7 @@ class PartitionedRegionParser extends AbstractSingleBeanDefinitionParser {
// add partition attributes attributes
attrBuilder.addPropertyValue("partitionAttributes", parAttrBuilder.getBeanDefinition());
// add partition/overflow settings as attributes
builder.addPropertyValue("attributes", attrBuilder.getBeanDefinition());
}

View File

@@ -179,8 +179,29 @@ use inner bean declarations.
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:element>
<xsd:element name="disk-store" type="diskStoreType" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Disk storage configuration for the defined region.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="persistent" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether the defined region is persistent or not. GemFire ensures that all the data you put into a region that
is configured for persistence will be written to disk in a way that it can be recovered the next time you create the
region. This allows data to be recovered after a machine or process failure or after an orderly shutdown and restart
of GemFire.
Default is false, meaning the regions are not persisted.
Note: Persistence for partitioned regions is supported only from GemFire 6.5 onwards.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -217,28 +238,7 @@ arbitrarily pick one.
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="disk-store" type="diskStoreType" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Disk storage configuration for the defined region.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="persistent" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether the defined region is persistent or not. GemFire ensures that all the data you put into a region that
is configured for persistence will be written to disk in a way that it can be recovered the next time you create the
region. This allows data to be recovered after a machine or process failure or after an orderly shutdown and restart
of GemFire.
Default is false, meaning the regions are not persisted.
Note: Persistence for partitioned regions is supported only from GemFire 6.5 onwards.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -600,8 +600,8 @@ which it receives its data. The client can hold some data locally or forward all
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="readOnlyRegionType">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:choice>
<xsd:sequence>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="key-interest">
<xsd:annotation>
<xsd:documentation><![CDATA[
@@ -649,11 +649,32 @@ Regular expression based interest. If the pattern is '.*' then all keys of any t
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:element name="eviction" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
Eviction policy for the partitioned region.
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="evictionType">
<xsd:attribute name="action" type="evictionActionType" default="LOCAL_DESTROY">
<xsd:annotation>
<xsd:documentation><![CDATA[
The action to take when performing eviction.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="data-policy" use="optional" default="NORMAL">
<xsd:annotation>
<xsd:documentation><![CDATA[
The data policy for this client. Can be either 'EMPTY' or 'NORMAL' (the default).
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.
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

View File

@@ -21,10 +21,13 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.File;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.SimpleObjectSizer;
import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.client.Interest;
@@ -35,8 +38,13 @@ import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.CacheListener;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.EvictionAction;
import com.gemstone.gemfire.cache.EvictionAlgorithm;
import com.gemstone.gemfire.cache.EvictionAttributes;
import com.gemstone.gemfire.cache.InterestResultPolicy;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.util.ObjectSizer;
/**
* @author Costin Leau
@@ -83,6 +91,34 @@ public class ClientRegionNamespaceTest {
assertFalse((Boolean) TestUtils.readField("durable", regexInt));
assertEquals(InterestResultPolicy.KEYS_VALUES, TestUtils.readField("key", regexInt));
assertEquals(".*", TestUtils.readField("key", regexInt));
}
@Test
public void testPersistent() throws Exception {
assertTrue(context.containsBean("persistent"));
ClientRegionFactoryBean fb = context.getBean("&persistent", ClientRegionFactoryBean.class);
assertEquals(DataPolicy.PERSISTENT_REPLICATE, TestUtils.readField("dataPolicy", fb));
assertEquals(Scope.LOCAL, TestUtils.readField("scope", fb));
RegionAttributes attrs = TestUtils.readField("attributes", fb);
File[] diskDirs = attrs.getDiskDirs();
assertEquals(1, diskDirs.length);
int[] diskDirSizes = attrs.getDiskDirSizes();
assertEquals(1, diskDirSizes.length);
assertEquals(1, diskDirSizes[0]);
}
@Test
public void testOverflowToDisk() throws Exception {
assertTrue(context.containsBean("overflow"));
ClientRegionFactoryBean fb = context.getBean("&overflow", ClientRegionFactoryBean.class);
assertEquals(DataPolicy.NORMAL, TestUtils.readField("dataPolicy", fb));
RegionAttributes attrs = TestUtils.readField("attributes", fb);
EvictionAttributes evicAttr = attrs.getEvictionAttributes();
assertEquals(EvictionAction.LOCAL_DESTROY, evicAttr.getAction());
assertEquals(EvictionAlgorithm.LRU_MEMORY, evicAttr.getAlgorithm());
// for some reason GemFire resets this to 56 on my machine (not sure why)
//assertEquals(10, evicAttr.getMaximum());
ObjectSizer sizer = evicAttr.getObjectSizer();
assertEquals(SimpleObjectSizer.class, sizer.getClass());
}
}

View File

@@ -31,5 +31,23 @@
<gfe:pool id="gemfire-pool" subscription-enabled="false">
<gfe:locator host="localhost" port="40403"/>
</gfe:pool>
<gfe:client-region id="persistent" pool-name="gemfire-pool" persistent="true">
<gfe:disk-store queue-size="50" auto-compact="true" max-oplog-size="10" synchronous-write="false" time-interval="9999">
<gfe:disk-dir location="./" max-size="1"/>
</gfe:disk-store>
</gfe:client-region>
<gfe:client-region id="overflow" pool-name="gemfire-pool">
<gfe:disk-store queue-size="50" auto-compact="true" max-oplog-size="10" synchronous-write="false" time-interval="9999">
<gfe:disk-dir location="./" max-size="1"/>
</gfe:disk-store>
<gfe:eviction type="MEMORY_SIZE" threshold="10" action="LOCAL_DESTROY">
<gfe:object-sizer>
<bean class="org.springframework.data.gemfire.SimpleObjectSizer"/>
</gfe:object-sizer>
</gfe:eviction>
</gfe:client-region>
</beans>