This is an automated email from the ASF dual-hosted git repository.

jinmeiliao pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new f286ec4  GEODE-6944: add support for *REDUNDANT* regionType (#3957)
f286ec4 is described below

commit f286ec451684b5d9047c661087a506281c587043
Author: Jinmei Liao <[email protected]>
AuthorDate: Mon Aug 26 19:01:56 2019 -0700

    GEODE-6944: add support for *REDUNDANT* regionType (#3957)
    
    Co-authored-by: Darrel Schneider <[email protected]>
---
 .../configuration/converters/RegionConverter.java  | 126 +++++++++++++++------
 .../realizers/RegionConfigRealizer.java            |  27 +----
 .../validators/RegionConfigValidator.java          |  16 +++
 .../sanctioned-geode-management-serializables.txt  |   2 +-
 .../converters/RegionConverterTest.java            |  78 +++++++++++--
 .../mutators/RegionConfigManagerTest.java          |   4 +-
 .../realizers/RegionConfigRealizerTest.java        |  40 +++++--
 .../validators/RegionConfigValidatorTest.java      |  57 ++++++++++
 .../geode/cache/configuration/RegionType.java      | 111 +++++++++++++++---
 .../geode/management/configuration/Region.java     |  26 ++++-
 .../geode/management/configuration/RegionTest.java |  46 +++++++-
 11 files changed, 428 insertions(+), 105 deletions(-)

diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/RegionConverter.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/RegionConverter.java
index 9bed6fd..77632af 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/RegionConverter.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/converters/RegionConverter.java
@@ -15,6 +15,9 @@
 
 package org.apache.geode.management.internal.configuration.converters;
 
+
+import java.util.Optional;
+
 import org.apache.geode.cache.configuration.EnumActionDestroyOverflow;
 import org.apache.geode.cache.configuration.RegionAttributesDataPolicy;
 import org.apache.geode.cache.configuration.RegionAttributesScope;
@@ -28,25 +31,17 @@ public class RegionConverter extends 
ConfigurationConverter<Region, RegionConfig
   protected Region fromNonNullXmlObject(RegionConfig xmlObject) {
     Region region = new Region();
     region.setName(xmlObject.getName());
-    if (xmlObject.getType() == null) {
-      // older gfsh would generate the region xml without the refid/type. we 
will not
-      // support showing these regions in management rest api for now.
-      region.setType(RegionType.UNSUPPORTED);
-    } else {
-      try {
-        region.setType(RegionType.valueOf(xmlObject.getType()));
-      } catch (IllegalArgumentException e) {
-        // Management rest api will not support showing regions with "LOCAL*" 
types or user defined
-        // refids
-        region.setType(RegionType.UNSUPPORTED);
-      }
-    }
     RegionAttributesType regionAttributes = xmlObject.getRegionAttributes();
+    region.setType(getRegionType(xmlObject.getType(), regionAttributes));
 
     if (regionAttributes != null) {
       region.setDiskStoreName(regionAttributes.getDiskStoreName());
       region.setKeyConstraint(regionAttributes.getKeyConstraint());
       region.setValueConstraint(regionAttributes.getValueConstraint());
+      Optional.ofNullable(regionAttributes.getPartitionAttributes())
+          .flatMap(
+              partitionAttributes -> 
Optional.ofNullable(partitionAttributes.getRedundantCopies()))
+          .ifPresent(copies -> 
region.setRedundantCopies(Integer.parseInt(copies)));
     }
     return region;
   }
@@ -65,30 +60,108 @@ public class RegionConverter extends 
ConfigurationConverter<Region, RegionConfig
     attributesType.setKeyConstraint(configObject.getKeyConstraint());
     attributesType.setValueConstraint(configObject.getValueConstraint());
     region.setRegionAttributes(attributesType);
+
+    if (configObject.getRedundantCopies() != null) {
+      RegionAttributesType.PartitionAttributes partitionAttributes =
+          new RegionAttributesType.PartitionAttributes();
+      
partitionAttributes.setRedundantCopies(configObject.getRedundantCopies().toString());
+      attributesType.setPartitionAttributes(partitionAttributes);
+    }
     return region;
   }
 
+  /**
+   * Data policy to regionType is almost a 1-to-1 mapping, except in
+   * the case of DataPolicy.PARTITION, we will need to see the local max memory
+   * to determine if it's a PARTITION type or a PARTITION_PROXY type.
+   *
+   * we do our best to infer the type from the existing xml attributes. For 
data
+   * policies not supported by management rest api (for example, NORMAL and 
PRELOADED)
+   * it will show as UNSUPPORTED
+   */
+  public RegionType getRegionType(String refid, RegionAttributesType 
regionAttributes) {
+    if (refid != null) {
+      try {
+        return RegionType.valueOf(refid);
+      } catch (Exception e) {
+        return RegionType.UNSUPPORTED;
+      }
+    }
+
+    // if refid is null, we will try to determine the type based on the region 
attributes
+    if (regionAttributes == null) {
+      return RegionType.UNSUPPORTED;
+    }
+    RegionAttributesDataPolicy dataPolicy = regionAttributes.getDataPolicy();
+
+    if (dataPolicy == null) {
+      return RegionType.UNSUPPORTED;
+    }
+
+    switch (dataPolicy) {
+      case PARTITION: {
+        RegionAttributesType.PartitionAttributes partitionAttributes =
+            regionAttributes.getPartitionAttributes();
+        if (partitionAttributes != null && 
"0".equals(partitionAttributes.getLocalMaxMemory())) {
+          return RegionType.PARTITION_PROXY;
+        }
+        return RegionType.PARTITION;
+      }
+      case PERSISTENT_PARTITION: {
+        return RegionType.PARTITION_PERSISTENT;
+      }
+      case PERSISTENT_REPLICATE: {
+        return RegionType.REPLICATE_PERSISTENT;
+      }
+      case REPLICATE: {
+        return RegionType.REPLICATE;
+      }
+      case EMPTY: {
+        return RegionType.REPLICATE_PROXY;
+      }
+    }
+    return RegionType.UNSUPPORTED;
+  }
+
+
   public RegionAttributesType createRegionAttributesByType(String type) {
     RegionAttributesType regionAttributes = new RegionAttributesType();
     switch (type) {
+      // these are supported by the management rest api
       case "PARTITION": {
         regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PARTITION);
         break;
       }
+      case "PARTITION_PERSISTENT": {
+        
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_PARTITION);
+        break;
+      }
+      case "PARTITION_PROXY": {
+        regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PARTITION);
+        regionAttributes.setLocalMaxMemory("0");
+        break;
+      }
       case "REPLICATE": {
         regionAttributes.setDataPolicy(RegionAttributesDataPolicy.REPLICATE);
         regionAttributes.setScope(RegionAttributesScope.DISTRIBUTED_ACK);
         break;
       }
+      case "REPLICATE_PERSISTENT": {
+        
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_REPLICATE);
+        regionAttributes.setScope(RegionAttributesScope.DISTRIBUTED_ACK);
+        break;
+      }
+      case "REPLICATE_PROXY": {
+        regionAttributes.setDataPolicy(RegionAttributesDataPolicy.EMPTY);
+        regionAttributes.setScope(RegionAttributesScope.DISTRIBUTED_ACK);
+        break;
+      }
       case "PARTITION_REDUNDANT": {
         regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PARTITION);
         regionAttributes.setRedundantCopy("1");
         break;
       }
-      case "PARTITION_PERSISTENT": {
-        
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_PARTITION);
-        break;
-      }
+
       case "PARTITION_REDUNDANT_PERSISTENT": {
         
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_PARTITION);
         regionAttributes.setRedundantCopy("1");
@@ -134,19 +207,12 @@ public class RegionConverter extends 
ConfigurationConverter<Region, RegionConfig
             
.setLruHeapPercentageEvictionAction(EnumActionDestroyOverflow.LOCAL_DESTROY);
         break;
       }
-
-      case "REPLICATE_PERSISTENT": {
-        
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_REPLICATE);
-        regionAttributes.setScope(RegionAttributesScope.DISTRIBUTED_ACK);
-        break;
-      }
       case "REPLICATE_OVERFLOW": {
         regionAttributes.setDataPolicy(RegionAttributesDataPolicy.REPLICATE);
         regionAttributes.setScope(RegionAttributesScope.DISTRIBUTED_ACK);
         regionAttributes
             
.setLruHeapPercentageEvictionAction(EnumActionDestroyOverflow.OVERFLOW_TO_DISK);
         break;
-
       }
       case "REPLICATE_PERSISTENT_OVERFLOW": {
         
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_REPLICATE);
@@ -194,22 +260,14 @@ public class RegionConverter extends 
ConfigurationConverter<Region, RegionConfig
             
.setLruHeapPercentageEvictionAction(EnumActionDestroyOverflow.OVERFLOW_TO_DISK);
         break;
       }
-      case "PARTITION_PROXY": {
-        regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PARTITION);
-        regionAttributes.setLocalMaxMemory("0");
-        break;
-      }
+
       case "PARTITION_PROXY_REDUNDANT": {
         regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PARTITION);
         regionAttributes.setLocalMaxMemory("0");
         regionAttributes.setRedundantCopy("1");
         break;
       }
-      case "REPLICATE_PROXY": {
-        regionAttributes.setDataPolicy(RegionAttributesDataPolicy.EMPTY);
-        regionAttributes.setScope(RegionAttributesScope.DISTRIBUTED_ACK);
-        break;
-      }
+
       default:
         throw new IllegalArgumentException("invalid type " + type);
     }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizer.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizer.java
index ec8b673..b946d56 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizer.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizer.java
@@ -57,9 +57,8 @@ public class RegionConfigRealizer
    */
   @Override
   public RealizationResult create(Region regionConfig, InternalCache cache) {
-    RegionFactory factory = getRegionFactory(cache, regionConfig);
-    factory.create(regionConfig.getName());
-    return new RealizationResult().setMessage("Region successfully created.");
+    RegionConfig xmlConfig = converter.fromConfigObject(regionConfig);
+    return create(xmlConfig, regionConfig.getName(), cache);
   }
 
   /**
@@ -86,28 +85,6 @@ public class RegionConfigRealizer
     return new RealizationResult().setMessage("Region successfully created.");
   }
 
-  RegionFactory getRegionFactory(Cache cache, Region regionConfig) {
-    RegionFactory factory =
-        cache.createRegionFactory(regionConfig.getType().name());
-    if (regionConfig.getDiskStoreName() != null) {
-      factory.setDiskStoreName(regionConfig.getDiskStoreName());
-    }
-    final String keyConstraint = regionConfig.getKeyConstraint();
-    final String valueConstraint = regionConfig.getValueConstraint();
-    if (keyConstraint != null && !keyConstraint.isEmpty()) {
-      Class<Object> keyConstraintClass =
-          CliUtil.forName(keyConstraint, 
CliStrings.CREATE_REGION__KEYCONSTRAINT);
-      factory.setKeyConstraint(keyConstraintClass);
-    }
-
-    if (valueConstraint != null && !valueConstraint.isEmpty()) {
-      Class<Object> valueConstraintClass =
-          CliUtil.forName(valueConstraint, 
CliStrings.CREATE_REGION__VALUECONSTRAINT);
-      factory.setValueConstraint(valueConstraintClass);
-    }
-    return factory;
-  }
-
   private RegionFactory getRegionFactory(Cache cache, RegionAttributesType 
regionAttributes) {
     RegionFactory factory = cache.createRegionFactory();
 
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java
index d16e056..32c82a9 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidator.java
@@ -62,6 +62,22 @@ public class RegionConfigValidator implements 
ConfigurationValidator<Region> {
     if (config.getType() == RegionType.UNSUPPORTED) {
       throw new IllegalArgumentException(("Region type is unsupported."));
     }
+
+    Integer redundantCopies = config.getRedundantCopies();
+    if (config.getType().withRedundant() && redundantCopies == 0) {
+      throw new IllegalArgumentException(
+          "redundantCopies cannot be 0 when the type has redundancy.");
+    }
+
+    if (redundantCopies != null && (redundantCopies < 0 || redundantCopies > 
3)) {
+      throw new IllegalArgumentException(
+          "redundantCopies cannot be less than 0 or greater than 3.");
+    }
+
+    if (!config.getType().withPartition() && config.getRedundantCopies() != 
null) {
+      throw new IllegalArgumentException("redundantCopies can only be set with 
PARTITION regions.");
+    }
+
     RegionNameValidation.validate(config.getName());
 
     // additional authorization
diff --git 
a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
 
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
index 0f63eba..14dd558 100644
--- 
a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
+++ 
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-management-serializables.txt
@@ -37,7 +37,7 @@ 
org/apache/geode/management/configuration/GatewayReceiver,false,endPort:java/lan
 
org/apache/geode/management/configuration/Index,false,expression:java/lang/String,keyIndex:java/lang/Boolean,name:java/lang/String,regionPath:java/lang/String
 
org/apache/geode/management/configuration/MemberConfig,false,id:java/lang/String
 
org/apache/geode/management/configuration/Pdx,false,diskStoreName:java/lang/String,ignoreUnreadFields:java/lang/Boolean,pdxSerializer:org/apache/geode/management/configuration/ClassName,persistent:java/lang/Boolean,readSerialized:java/lang/Boolean
-org/apache/geode/management/configuration/Region,false,diskStoreName:java/lang/String,keyConstraint:java/lang/String,name:java/lang/String,type:org/apache/geode/cache/configuration/RegionType,valueConstraint:java/lang/String
+org/apache/geode/management/configuration/Region,false,diskStoreName:java/lang/String,keyConstraint:java/lang/String,name:java/lang/String,redundantCopies:java/lang/Integer,type:org/apache/geode/cache/configuration/RegionType,valueConstraint:java/lang/String
 
org/apache/geode/management/runtime/CacheServerInfo,true,1,bindAddress:java/lang/String,isRunning:boolean,maxConnections:int,maxThreads:int,port:int
 
org/apache/geode/management/runtime/GatewayReceiverInfo,false,bindAddress:java/lang/String,connectedSenders:java/lang/String[],hostnameForSenders:java/lang/String,port:int,running:boolean,senderCount:int
 
org/apache/geode/management/runtime/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:long,host:java/lang/String,hostedRegions:java/util/Set,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:long,isCoordinator:boolean,isSecured:boolean,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:long,of
 [...]
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/converters/RegionConverterTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/converters/RegionConverterTest.java
index a43f686..2eeeaac 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/converters/RegionConverterTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/converters/RegionConverterTest.java
@@ -16,6 +16,7 @@
 package org.apache.geode.management.internal.configuration.converters;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.io.File;
 import java.net.URL;
@@ -49,7 +50,7 @@ public class RegionConverterTest {
   @Test
   public void fromXmlWithNameType() throws Exception {
     config.setName("test");
-    config.setType("REPLICATE");
+    
config.setRegionAttributes(converter.createRegionAttributesByType("REPLICATE"));
 
     Region region = converter.fromXmlObject(config);
     assertThat(region.getName()).isEqualTo("test");
@@ -59,26 +60,32 @@ public class RegionConverterTest {
   @Test
   public void fromXmlWithAll() throws Exception {
     config.setName("test");
-    config.setType("REPLICATE");
+    
config.setRegionAttributes(converter.createRegionAttributesByType("PARTITION"));
 
-    RegionAttributesType attributesType = new RegionAttributesType();
+    RegionAttributesType attributesType = config.getRegionAttributes();
     attributesType.setValueConstraint("foo");
     attributesType.setKeyConstraint("bar");
     attributesType.setDiskStoreName("diskstore");
     config.setRegionAttributes(attributesType);
 
+    RegionAttributesType.PartitionAttributes partitionAttributes =
+        new RegionAttributesType.PartitionAttributes();
+    partitionAttributes.setRedundantCopies("2");
+    attributesType.setPartitionAttributes(partitionAttributes);
+
     Region region = converter.fromXmlObject(config);
     assertThat(region.getName()).isEqualTo("test");
-    assertThat(region.getType()).isEqualTo(RegionType.REPLICATE);
+    assertThat(region.getType()).isEqualTo(RegionType.PARTITION);
     assertThat(region.getValueConstraint()).isEqualTo("foo");
     assertThat(region.getKeyConstraint()).isEqualTo("bar");
     assertThat(region.getDiskStoreName()).isEqualTo("diskstore");
+    assertThat(region.getRedundantCopies()).isEqualTo(2);
   }
 
   @Test
   public void fromXmlWithLocalType() throws Exception {
     config.setName("test");
-    config.setType("LOCAL");
+    
config.setRegionAttributes(converter.createRegionAttributesByType("LOCAL"));
     
assertThat(converter.fromXmlObject(config).getType()).isEqualTo(RegionType.UNSUPPORTED);
   }
 
@@ -92,18 +99,20 @@ public class RegionConverterTest {
   @Test
   public void fromConfig() throws Exception {
     region.setName("test");
-    region.setType(RegionType.REPLICATE);
+    region.setType(RegionType.PARTITION);
     region.setValueConstraint("foo");
     region.setKeyConstraint("bar");
     region.setDiskStoreName("diskstore");
+    region.setRedundantCopies(2);
     RegionConfig config = converter.fromConfigObject(region);
     assertThat(config.getName()).isEqualTo("test");
-    assertThat(config.getType()).isEqualTo("REPLICATE");
+    assertThat(config.getType()).isEqualTo("PARTITION");
     RegionAttributesType regionAttributes = config.getRegionAttributes();
-    
assertThat(regionAttributes.getDataPolicy()).isEqualTo(RegionAttributesDataPolicy.REPLICATE);
+    
assertThat(regionAttributes.getDataPolicy()).isEqualTo(RegionAttributesDataPolicy.PARTITION);
     assertThat(regionAttributes.getKeyConstraint()).isEqualTo("bar");
     assertThat(regionAttributes.getValueConstraint()).isEqualTo("foo");
     assertThat(regionAttributes.getDiskStoreName()).isEqualTo("diskstore");
+    
assertThat(regionAttributes.getPartitionAttributes().getRedundantCopies()).isEqualTo("2");
   }
 
   @Test
@@ -123,4 +132,57 @@ public class RegionConverterTest {
       
assertThat(config).isEqualToComparingFieldByFieldRecursively(masterRegion);
     }
   }
+
+  @Test
+  public void getRegionType() throws Exception {
+    assertThat(converter.getRegionType("ABC", null))
+        .isEqualTo(RegionType.UNSUPPORTED);
+
+    assertThat(converter.getRegionType("PARTITION_REDUNDANT", null))
+        .isEqualTo(RegionType.PARTITION_REDUNDANT);
+    assertThat(converter.getRegionType(null, 
null)).isEqualTo(RegionType.UNSUPPORTED);
+
+    RegionAttributesType regionAttributes = new RegionAttributesType();
+    assertThat(converter.getRegionType(null, 
regionAttributes)).isEqualTo(RegionType.UNSUPPORTED);
+
+    regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PARTITION);
+    assertThat(converter.getRegionType(null, 
regionAttributes)).isEqualTo(RegionType.PARTITION);
+
+    RegionAttributesType.PartitionAttributes pAttributes =
+        new RegionAttributesType.PartitionAttributes();
+    pAttributes.setLocalMaxMemory("20000");
+    regionAttributes.setPartitionAttributes(pAttributes);
+    assertThat(converter.getRegionType(null, 
regionAttributes)).isEqualTo(RegionType.PARTITION);
+
+    pAttributes.setLocalMaxMemory("0");
+    assertThat(converter.getRegionType(null, regionAttributes))
+        .isEqualTo(RegionType.PARTITION_PROXY);
+
+    
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_PARTITION);
+    assertThat(converter.getRegionType(null, regionAttributes))
+        .isEqualTo(RegionType.PARTITION_PERSISTENT);
+
+    regionAttributes.setDataPolicy(RegionAttributesDataPolicy.REPLICATE);
+    assertThat(converter.getRegionType(null, 
regionAttributes)).isEqualTo(RegionType.REPLICATE);
+
+    
regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PERSISTENT_REPLICATE);
+    assertThat(converter.getRegionType(null, regionAttributes))
+        .isEqualTo(RegionType.REPLICATE_PERSISTENT);
+
+    regionAttributes.setDataPolicy(RegionAttributesDataPolicy.EMPTY);
+    assertThat(converter.getRegionType(null, regionAttributes))
+        .isEqualTo(RegionType.REPLICATE_PROXY);
+
+    regionAttributes.setDataPolicy(RegionAttributesDataPolicy.NORMAL);
+    assertThat(converter.getRegionType(null, 
regionAttributes)).isEqualTo(RegionType.UNSUPPORTED);
+
+    regionAttributes.setDataPolicy(RegionAttributesDataPolicy.PRELOADED);
+    assertThat(converter.getRegionType(null, 
regionAttributes)).isEqualTo(RegionType.UNSUPPORTED);
+  }
+
+  @Test
+  public void createRegionAttributesByInvalidType() throws Exception {
+    assertThatThrownBy(() -> converter.createRegionAttributesByType("abc"))
+        .isInstanceOf(IllegalArgumentException.class);
+  }
 }
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManagerTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManagerTest.java
index d3ed2a1..6e56ff8 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManagerTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/mutators/RegionConfigManagerTest.java
@@ -46,8 +46,8 @@ public class RegionConfigManagerTest {
 
   @Test
   public void compatibleWithSameType() throws Exception {
-    config1.setType(RegionType.PARTITION_HEAP_LRU);
-    config2.setType(RegionType.PARTITION_HEAP_LRU);
+    config1.setType(RegionType.PARTITION_PERSISTENT);
+    config2.setType(RegionType.PARTITION_PERSISTENT);
     manager.checkCompatibility(config1, "group", config2);
   }
 
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizerTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizerTest.java
index c41f978..198f25b 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizerTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/realizers/RegionConfigRealizerTest.java
@@ -16,8 +16,8 @@
  */
 package org.apache.geode.management.internal.configuration.realizers;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -25,7 +25,10 @@ import static org.powermock.api.mockito.PowerMockito.when;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 
+import org.apache.geode.cache.DataPolicy;
+import org.apache.geode.cache.PartitionAttributes;
 import org.apache.geode.cache.RegionFactory;
 import org.apache.geode.cache.configuration.RegionType;
 import org.apache.geode.internal.cache.InternalCache;
@@ -45,29 +48,28 @@ public class RegionConfigRealizerTest {
     cache = mock(InternalCache.class);
     validator = new RegionConfigValidator(cache);
     regionFactory = mock(RegionFactory.class);
-    when(cache.createRegionFactory(anyString())).thenReturn(regionFactory);
+    when(cache.createRegionFactory()).thenReturn(regionFactory);
     realizer = new RegionConfigRealizer();
     config = new Region();
+    config.setName("test");
   }
 
   @Test
   public void createsPartitionedInCache() {
-    config.setName("regionName");
     config.setType(RegionType.PARTITION);
     validator.validate(CacheElementOperation.CREATE, config);
     realizer.create(config, cache);
-    verify(cache).createRegionFactory("PARTITION");
-    verify(regionFactory).create("regionName");
+    verify(regionFactory).create("test");
+    verify(regionFactory).setDataPolicy(DataPolicy.PARTITION);
   }
 
   @Test
   public void createsReplicateInCache() {
-    config.setName("regionName");
     config.setType(RegionType.REPLICATE);
     validator.validate(CacheElementOperation.CREATE, config);
     realizer.create(config, cache);
-    verify(cache).createRegionFactory("REPLICATE");
-    verify(regionFactory).create("regionName");
+    verify(regionFactory).create("test");
+    verify(regionFactory).setDataPolicy(DataPolicy.REPLICATE);
   }
 
   @Test
@@ -77,11 +79,25 @@ public class RegionConfigRealizerTest {
     config.setKeyConstraint("java.lang.String");
     config.setValueConstraint("java.lang.Boolean");
 
-    realizer.getRegionFactory(cache, config);
+    realizer.create(config, cache);
     verify(regionFactory).setKeyConstraint(String.class);
     verify(regionFactory).setValueConstraint(Boolean.class);
     verify(regionFactory).setDiskStoreName("diskstore");
-    verify(cache).createRegionFactory("REPLICATE");
+    verify(regionFactory).setDataPolicy(DataPolicy.REPLICATE);
+  }
+
+
+  @Test
+  public void createPartitionRegion() throws Exception {
+    config.setType(RegionType.PARTITION);
+    config.setRedundantCopies(2);
+
+    realizer.create(config, cache);
+    verify(regionFactory).setDataPolicy(DataPolicy.PARTITION);
+    ArgumentCaptor<PartitionAttributes> argumentCaptor =
+        ArgumentCaptor.forClass(PartitionAttributes.class);
+    verify(regionFactory).setPartitionAttributes(argumentCaptor.capture());
+    assertThat(argumentCaptor.getValue().getRedundantCopies()).isEqualTo(2);
   }
 
   @Test
@@ -91,10 +107,10 @@ public class RegionConfigRealizerTest {
     config.setKeyConstraint(null);
     config.setValueConstraint(null);
 
-    realizer.getRegionFactory(cache, config);
+    realizer.create(config, cache);
     verify(regionFactory, never()).setKeyConstraint(any());
     verify(regionFactory, never()).setValueConstraint(any());
     verify(regionFactory, never()).setDiskStoreName(any());
-    verify(cache).createRegionFactory("REPLICATE");
+    verify(regionFactory).setDataPolicy(DataPolicy.REPLICATE);
   }
 }
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java
index cc4b3d0..3d0a9cd 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/validators/RegionConfigValidatorTest.java
@@ -110,4 +110,61 @@ public class RegionConfigValidatorTest {
         .hasMessageContaining(
             "Region type is unsupported.");
   }
+
+  @Test
+  public void validateDefaultRedundancy() throws Exception {
+    config.setName("test");
+    config.setType(RegionType.PARTITION_REDUNDANT);
+    // the config without the explicit redundancy is valid
+    validator.validate(CacheElementOperation.CREATE, config);
+  }
+
+  @Test
+  public void invalidRedundancy() throws Exception {
+    config.setName("test");
+    config.setType(RegionType.PARTITION_REDUNDANT);
+    config.setRedundantCopies(0);
+    assertThatThrownBy(() -> validator.validate(CacheElementOperation.CREATE, 
config)).isInstanceOf(
+        IllegalArgumentException.class)
+        .hasMessageContaining(
+            "redundantCopies cannot be 0");
+  }
+
+  @Test
+  public void invalidRedundancy1() throws Exception {
+    config.setName("test");
+    config.setRedundantCopies(0);
+    config.setType(RegionType.PARTITION_REDUNDANT);
+    assertThatThrownBy(() -> validator.validate(CacheElementOperation.CREATE, 
config)).isInstanceOf(
+        IllegalArgumentException.class)
+        .hasMessageContaining(
+            "redundantCopies cannot be 0");
+
+    config.setRedundantCopies(-1);
+    config.setType(RegionType.PARTITION_REDUNDANT);
+    assertThatThrownBy(() -> validator.validate(CacheElementOperation.CREATE, 
config)).isInstanceOf(
+        IllegalArgumentException.class)
+        .hasMessageContaining(
+            "redundantCopies cannot be less than 0 or greater than 3.");
+
+    config.setRedundantCopies(4);
+    config.setType(RegionType.PARTITION_REDUNDANT);
+    assertThatThrownBy(() -> validator.validate(CacheElementOperation.CREATE, 
config)).isInstanceOf(
+        IllegalArgumentException.class)
+        .hasMessageContaining(
+            "redundantCopies cannot be less than 0 or greater than 3.");
+
+  }
+
+  @Test
+  public void replicateWithRedundancy() throws Exception {
+    config.setName("test");
+    config.setType(RegionType.REPLICATE);
+    config.setRedundantCopies(2);
+
+    assertThatThrownBy(() -> validator.validate(CacheElementOperation.CREATE, 
config)).isInstanceOf(
+        IllegalArgumentException.class)
+        .hasMessageContaining(
+            "redundantCopies can only be set with PARTITION regions.");
+  }
 }
diff --git 
a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionType.java
 
b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionType.java
index 39d58b8..5df4348 100644
--- 
a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionType.java
+++ 
b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionType.java
@@ -18,34 +18,111 @@ package org.apache.geode.cache.configuration;
 import org.apache.geode.annotations.Experimental;
 
 /**
- * these are the region types supported by Cluster Management V2 API. The 
attributes of these
- * region types are the same as their namesakes in RegionShortcut
+ * these are the region types supported by Cluster Management V2 API.
+ * these corresponds to a subset of data policies
  */
 @Experimental
 public enum RegionType {
   PARTITION,
-  PARTITION_REDUNDANT,
   PARTITION_PERSISTENT,
-  PARTITION_REDUNDANT_PERSISTENT,
-  PARTITION_OVERFLOW,
-  PARTITION_REDUNDANT_OVERFLOW,
-  PARTITION_PERSISTENT_OVERFLOW,
-  PARTITION_REDUNDANT_PERSISTENT_OVERFLOW,
-  PARTITION_HEAP_LRU,
-  PARTITION_REDUNDANT_HEAP_LRU,
-
   PARTITION_PROXY,
-  PARTITION_PROXY_REDUNDANT,
 
   REPLICATE,
   REPLICATE_PERSISTENT,
-  REPLICATE_OVERFLOW,
-  REPLICATE_PERSISTENT_OVERFLOW,
-  REPLICATE_HEAP_LRU,
-
   REPLICATE_PROXY,
 
   // this is used to represent regions not supported by the management V2 API. 
For example Gfsh can
   // create regions with "LOCAL*" types
-  UNSUPPORTED;
+  UNSUPPORTED,
+
+  /**
+   * @deprecated use PARTITION and set the redundancy level to 1
+   */
+  @Deprecated
+  PARTITION_REDUNDANT,
+  /**
+   * @deprecated use PARTITION_PERSISTENT and set the redundancy level to 1
+   */
+  @Deprecated
+  PARTITION_REDUNDANT_PERSISTENT,
+  /**
+   * @deprecated use PARTITION and set the evictionAction to OVERFLOW_TO_DISK
+   */
+  // PARTITION_OVERFLOW,
+  /**
+   * @deprecated use PARTITION and set the redundancy level to 1, and set the 
evictionAction to
+   *             OVERFLOW_TO_DISK
+   */
+
+  // PARTITION_REDUNDANT_OVERFLOW,
+  /**
+   * @deprecated use PARTITION_PERSISTENT and set the evictionAction to 
OVERFLOW_TO_DISK
+   */
+  // PARTITION_PERSISTENT_OVERFLOW,
+  /**
+   * @deprecated use PARTITION_PERSISTENT and set the redundancy level to 1 
and set the
+   *             evictionAction to OVERFLOW_TO_DISK
+   */
+  // PARTITION_REDUNDANT_PERSISTENT_OVERFLOW,
+  /**
+   * @deprecated use PARTITION and set the evictionAction to LOCAL_DESTROY
+   */
+  // PARTITION_HEAP_LRU,
+  /**
+   * @deprecated use PARTITION and set the redundancy level to 1 and set the 
evictionAction to
+   *             LOCAL_DESTROY
+   */
+  // PARTITION_REDUNDANT_HEAP_LRU,
+  /**
+   * @deprecated use PARTITION_PROXY and set the redundancy level to 1
+   */
+  @Deprecated
+  PARTITION_PROXY_REDUNDANT;
+  /**
+   * @deprecated use REPLICATE and set the evictionAction to OVERFLOW_TO_DISK
+   */
+  // REPLICATE_OVERFLOW,
+  /**
+   * @deprecated use REPLICATE_PERSISTENT and set the evictionAction to 
OVERFLOW_TO_DISK
+   */
+  // REPLICATE_PERSISTENT_OVERFLOW,
+  /**
+   * @deprecated use REPLICATE and set the evictionAction to LOCAL_DESTROY
+   */
+  // REPLICATE_HEAP_LRU;
+
+  /**
+   * @return if the type contains "PROXY"
+   */
+  public boolean withProxy() {
+    return name().contains("PROXY");
+  }
+
+  /**
+   * @return if the type contains "PERSISTENT"
+   */
+  public boolean withPersistent() {
+    return name().contains("PERSISTENT");
+  }
+
+  /**
+   * @return if the type contains "REPLICATE"
+   */
+  public boolean withReplicate() {
+    return name().contains("REPLICATE");
+  }
+
+  /**
+   * @return if the type contains "PARTITION"
+   */
+  public boolean withPartition() {
+    return name().contains("PARTITION");
+  }
+
+  /**
+   * @return if the type contains "REDUNDANT"
+   */
+  public boolean withRedundant() {
+    return name().contains("REDUNDANT");
+  }
 }
diff --git 
a/geode-management/src/main/java/org/apache/geode/management/configuration/Region.java
 
b/geode-management/src/main/java/org/apache/geode/management/configuration/Region.java
index 87920de..c5da2cd 100644
--- 
a/geode-management/src/main/java/org/apache/geode/management/configuration/Region.java
+++ 
b/geode-management/src/main/java/org/apache/geode/management/configuration/Region.java
@@ -25,6 +25,12 @@ import org.apache.geode.management.api.CorrespondWith;
 import org.apache.geode.management.api.RestfulEndpoint;
 import org.apache.geode.management.runtime.RuntimeRegionInfo;
 
+/**
+ * this holds the region attributes you can configure using management rest api
+ *
+ * for regions created using gfsh but listed using management rest api, the 
attributes not supported
+ * by management rest api won't be shown.
+ */
 public class Region extends CacheElement implements RestfulEndpoint,
     CorrespondWith<RuntimeRegionInfo> {
   public static final String REGION_CONFIG_ENDPOINT = "/regions";
@@ -35,14 +41,10 @@ public class Region extends CacheElement implements 
RestfulEndpoint,
   private String keyConstraint;
   private String valueConstraint;
   private String diskStoreName;
+  private Integer redundantCopies;
 
   public Region() {}
 
-  public Region(String name, RegionType type) {
-    this.name = name;
-    this.type = type;
-  }
-
   @Override
   public boolean isGlobalRuntime() {
     return true;
@@ -89,6 +91,20 @@ public class Region extends CacheElement implements 
RestfulEndpoint,
     this.type = type;
   }
 
+  /**
+   * @return the redundant copies of a region
+   */
+  public Integer getRedundantCopies() {
+    if (type != null && type.withRedundant() && redundantCopies == null) {
+      return 1;
+    }
+    return redundantCopies;
+  }
+
+  public void setRedundantCopies(Integer redundantCopies) {
+    this.redundantCopies = redundantCopies;
+  }
+
   public String getKeyConstraint() {
     return keyConstraint;
   }
diff --git 
a/geode-management/src/test/java/org/apache/geode/management/configuration/RegionTest.java
 
b/geode-management/src/test/java/org/apache/geode/management/configuration/RegionTest.java
index 9215bbd..6e35fe1 100644
--- 
a/geode-management/src/test/java/org/apache/geode/management/configuration/RegionTest.java
+++ 
b/geode-management/src/test/java/org/apache/geode/management/configuration/RegionTest.java
@@ -30,6 +30,7 @@ import org.apache.geode.util.internal.GeodeJsonMapper;
 public class RegionTest {
 
   private Region regionConfig;
+  private static ObjectMapper mapper = GeodeJsonMapper.getMapper();
 
   @Before
   public void before() throws Exception {
@@ -54,7 +55,6 @@ public class RegionTest {
   @Test
   public void correctJson() throws Exception {
     String json = "{\"name\":\"test\", \"type\":\"REPLICATE\"}";
-    ObjectMapper mapper = GeodeJsonMapper.getMapper();
     regionConfig = mapper.readValue(json, Region.class);
     assertThat(regionConfig.getName()).isEqualTo("test");
     assertThat(regionConfig.getType()).isEqualTo(RegionType.REPLICATE);
@@ -79,4 +79,48 @@ public class RegionTest {
     assertThat(regionConfig.hasRuntimeInfo()).isTrue();
   }
 
+  @Test
+  public void parseJsonWithDeprecatedType() throws Exception {
+    String json = "{\"name\":\"test\", 
\"type\":\"PARTITION_REDUNDANT_PERSISTENT\"}";
+    regionConfig = mapper.readValue(json, Region.class);
+    assertThat(regionConfig.getName()).isEqualTo("test");
+    assertThat(regionConfig.getRedundantCopies()).isEqualTo(1);
+    
assertThat(regionConfig.getType()).isEqualTo(RegionType.PARTITION_REDUNDANT_PERSISTENT);
+
+    String resultJson = mapper.writeValueAsString(regionConfig);
+    
assertThat(resultJson).contains("\"type\":\"PARTITION_REDUNDANT_PERSISTENT\"")
+        .contains("\"redundantCopies\":1");
+
+    Region resultRegion = mapper.readValue(resultJson, Region.class);
+    assertThat(regionConfig.getName()).isEqualTo(resultRegion.getName());
+    assertThat(regionConfig.getType()).isEqualTo(resultRegion.getType());
+    
assertThat(regionConfig.getRedundantCopies()).isEqualTo(resultRegion.getRedundantCopies());
+  }
+
+  @Test
+  public void parseWithShortcutAndOtherOverridingAttributes() throws Exception 
{
+    String json =
+        "{\"name\":\"test\", \"redundantCopies\":0, 
\"type\":\"PARTITION_REDUNDANT_PERSISTENT\"}";
+    regionConfig = mapper.readValue(json, Region.class);
+    assertThat(regionConfig.getName()).isEqualTo("test");
+    assertThat(regionConfig.getRedundantCopies()).isEqualTo(0);
+    
assertThat(regionConfig.getType()).isEqualTo(RegionType.PARTITION_REDUNDANT_PERSISTENT);
+  }
+
+  @Test
+  public void redundancySetter() throws Exception {
+    regionConfig.setType(RegionType.PARTITION_REDUNDANT);
+    regionConfig.setRedundantCopies(3);
+    assertThat(regionConfig.getRedundantCopies()).isEqualTo(3);
+  }
+
+  @Test
+  public void redundant() throws Exception {
+    regionConfig.setType(RegionType.PARTITION_REDUNDANT);
+    assertThat(regionConfig.getRedundantCopies()).isEqualTo(1);
+
+    regionConfig.setType(RegionType.PARTITION);
+    assertThat(regionConfig.getRedundantCopies()).isNull();
+  }
+
 }

Reply via email to