SGF-22
+ add persistence and overflow support for client regions
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user