[ 
https://issues.apache.org/jira/browse/GEODE-4049?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16278886#comment-16278886
 ] 

ASF GitHub Bot commented on GEODE-4049:
---------------------------------------

jinmeiliao closed pull request #1118: GEODE-4049: refactor CreateRegionCommand 
and DestoryRegionCommand status
URL: https://github.com/apache/geode/pull/1118
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git 
a/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java 
b/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java
index b4a357f85a..733296dec2 100755
--- 
a/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java
+++ 
b/geode-core/src/main/java/org/apache/geode/cache/execute/FunctionContext.java
@@ -14,7 +14,10 @@
  */
 package org.apache.geode.cache.execute;
 
+import org.apache.logging.log4j.util.Strings;
+
 import org.apache.geode.cache.Cache;
+import org.apache.geode.distributed.DistributedMember;
 
 /**
  * Defines the execution context of a {@link Function}. It is required by the
@@ -77,4 +80,22 @@
   public boolean isPossibleDuplicate();
 
   public Cache getCache();
+
+  /**
+   * a convenience method to get the name of the member this function executes 
on. call this
+   * function once in your function execution to avoid performance issues.
+   *
+   * @return member name or id if name is blank
+   */
+  public default String getMemberName() {
+    DistributedMember member = 
getCache().getDistributedSystem().getDistributedMember();
+
+    // if this member has name, use it, otherwise, use the id
+    String memberName = member.getName();
+    if (!Strings.isBlank(memberName)) {
+      return memberName;
+    }
+
+    return member.getId();
+  }
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommand.java
index 0b46c0b239..ea0a636387 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommand.java
@@ -24,8 +24,6 @@
 import org.springframework.shell.core.annotation.CliOption;
 
 import org.apache.geode.cache.asyncqueue.internal.AsyncEventQueueFactoryImpl;
-import org.apache.geode.cache.execute.Function;
-import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.management.cli.ConverterHint;
 import org.apache.geode.management.cli.Result;
@@ -119,7 +117,7 @@ public Result createAsyncEventQueue(
         gatewaySubstitutionListener, listener, listenerProperties, 
forwardExpirationDestroy);
 
     CreateAsyncEventQueueFunction function = new 
CreateAsyncEventQueueFunction();
-    List<CliFunctionResult> results = execute(function, aeqArgs, 
targetMembers);
+    List<CliFunctionResult> results = executeAndGetFunctionResult(function, 
aeqArgs, targetMembers);
 
     if (results.size() == 0) {
       throw new RuntimeException("No results received.");
@@ -149,9 +147,4 @@ public Result createAsyncEventQueue(
     return commandResult;
   }
 
-  List<CliFunctionResult> execute(Function function, Object args,
-      Set<DistributedMember> targetMembers) {
-    ResultCollector rc = executeFunction(function, args, targetMembers);
-    return CliFunctionResult.cleanResults((List<?>) rc.getResult());
-  }
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateRegionCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateRegionCommand.java
index 5eeed3f637..732ca09210 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateRegionCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/CreateRegionCommand.java
@@ -344,35 +344,30 @@ public Result createRegion(
       }
     }
 
-    ResultCollector<?, ?> resultCollector =
-        executeFunction(RegionCreateFunction.INSTANCE, functionArgs, 
membersToCreateRegionOn);
-    @SuppressWarnings("unchecked")
-    List<CliFunctionResult> regionCreateResults =
-        (List<CliFunctionResult>) resultCollector.getResult();
+    List<CliFunctionResult> regionCreateResults = executeAndGetFunctionResult(
+        RegionCreateFunction.INSTANCE, functionArgs, membersToCreateRegionOn);
 
     TabularResultData tabularResultData = 
ResultBuilder.createTabularResultData();
-    final String errorPrefix = "ERROR: ";
+    boolean regionCreated = false;
     for (CliFunctionResult regionCreateResult : regionCreateResults) {
-      boolean success = regionCreateResult.isSuccessful();
       tabularResultData.accumulate("Member", 
regionCreateResult.getMemberIdOrName());
-      tabularResultData.accumulate("Status",
-          (success ? "" : errorPrefix) + regionCreateResult.getMessage());
-
-      if (success) {
+      if (regionCreateResult.isSuccessful()) {
+        tabularResultData.accumulate("Status", 
regionCreateResult.getMessage());
         xmlEntity.set(regionCreateResult.getXmlEntity());
+        regionCreated = true;
       } else {
-        tabularResultData.setStatus(Result.Status.ERROR);
+        tabularResultData.accumulate("Status", "ERROR: " + 
regionCreateResult.getErrorMessage());
       }
     }
 
+    tabularResultData.setStatus(regionCreated ? Result.Status.OK : 
Result.Status.ERROR);
     result = ResultBuilder.buildResult(tabularResultData);
-    verifyDistributedRegionMbean(cache, regionPath);
 
-    if (xmlEntity.get() != null) {
+    if (regionCreated) {
+      verifyDistributedRegionMbean(cache, regionPath);
       persistClusterConfiguration(result,
           () -> getSharedConfiguration().addXmlEntity(xmlEntity.get(), 
groups));
     }
-
     return result;
   }
 
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyDiskStoreCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyDiskStoreCommand.java
index 42d1ecde70..22db28d1b4 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyDiskStoreCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyDiskStoreCommand.java
@@ -22,12 +22,10 @@
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.shell.core.annotation.CliOption;
 
-import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.management.cli.CliMetaData;
 import org.apache.geode.management.cli.ConverterHint;
 import org.apache.geode.management.cli.Result;
-import org.apache.geode.management.internal.cli.CliUtil;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import 
org.apache.geode.management.internal.cli.functions.DestroyDiskStoreFunction;
 import 
org.apache.geode.management.internal.cli.functions.DestroyDiskStoreFunctionArgs;
@@ -54,7 +52,7 @@ public Result destroyDiskStore(
 
     TabularResultData tabularData = ResultBuilder.createTabularResultData();
 
-    Set<DistributedMember> targetMembers = CliUtil.findMembers(groups, null);
+    Set<DistributedMember> targetMembers = findMembers(groups, null);
 
     if (targetMembers.isEmpty()) {
       return 
ResultBuilder.createUserErrorResult(CliStrings.NO_MEMBERS_FOUND_MESSAGE);
@@ -62,9 +60,8 @@ public Result destroyDiskStore(
 
     DestroyDiskStoreFunctionArgs functionArgs = new 
DestroyDiskStoreFunctionArgs(name, ifExist);
 
-    ResultCollector<?, ?> rc =
-        CliUtil.executeFunction(new DestroyDiskStoreFunction(), functionArgs, 
targetMembers);
-    List<CliFunctionResult> results = CliFunctionResult.cleanResults((List<?>) 
rc.getResult());
+    List<CliFunctionResult> results =
+        executeAndGetFunctionResult(new DestroyDiskStoreFunction(), 
functionArgs, targetMembers);
 
     AtomicReference<XmlEntity> xmlEntity = new AtomicReference<>();
     for (CliFunctionResult result : results) {
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommand.java
index 13947ec469..e999ccca29 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommand.java
@@ -21,15 +21,17 @@
 import org.springframework.shell.core.annotation.CliCommand;
 import org.springframework.shell.core.annotation.CliOption;
 
-import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
 import org.apache.geode.management.cli.CliMetaData;
 import org.apache.geode.management.cli.ConverterHint;
 import org.apache.geode.management.cli.Result;
+import 
org.apache.geode.management.internal.cli.exceptions.EntityNotFoundException;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import 
org.apache.geode.management.internal.cli.functions.RegionDestroyFunction;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
+import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.management.internal.cli.result.ResultBuilder;
+import org.apache.geode.management.internal.cli.result.TabularResultData;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
 import org.apache.geode.management.internal.security.ResourceOperation;
 import org.apache.geode.security.ResourcePermission;
@@ -49,52 +51,49 @@ public Result destroyRegion(
     // regionPath should already be converted to have "/" in front of it.
     AtomicReference<XmlEntity> xmlEntity = new AtomicReference<>();
 
+    // this finds all the members that host this region. destroy will be 
called on each of these
+    // members since the region might be a scope.LOCAL region
     Set<DistributedMember> regionMembersList = 
findMembersForRegion(getCache(), regionPath);
 
     if (regionMembersList.size() == 0) {
-      if (ifExists) {
-        return ResultBuilder.createInfoResult("");
-      } else {
-        return ResultBuilder.createUserErrorResult(
-            
CliStrings.format(CliStrings.DESTROY_REGION__MSG__COULD_NOT_FIND_REGIONPATH_0_IN_GEODE,
-                regionPath, "jmx-manager-update-rate milliseconds"));
-      }
+      String message =
+          
CliStrings.format(CliStrings.DESTROY_REGION__MSG__COULD_NOT_FIND_REGIONPATH_0_IN_GEODE,
+              regionPath, "jmx-manager-update-rate milliseconds");
+      throw new EntityNotFoundException(message, ifExists);
     }
 
-    ResultCollector<?, ?> resultCollector =
-        executeFunction(RegionDestroyFunction.INSTANCE, regionPath, 
regionMembersList);
-    List<CliFunctionResult> resultsList = (List<CliFunctionResult>) 
resultCollector.getResult();
+    List<CliFunctionResult> resultsList =
+        executeAndGetFunctionResult(RegionDestroyFunction.INSTANCE, 
regionPath, regionMembersList);
+
+    // destroy is called on each member. If the region destroy is successful 
on one member, we
+    // deem the destroy action successful, since if one member destroy 
successfully, the subsequent
+    // destroy on a another member would probably throw 
RegionDestroyedException
+    TabularResultData tabularData = ResultBuilder.createTabularResultData();
 
-    // destroy is called on each member, if any error happens in any one of 
the member, we should
-    // deem the destroy not successful.
-    String errorMessage = null;
+    boolean regionDestroyed = false;
     for (CliFunctionResult functionResult : resultsList) {
+      tabularData.accumulate("Member", functionResult.getMemberIdOrName());
       if (functionResult.isSuccessful()) {
-        xmlEntity.set(functionResult.getXmlEntity());
-      } else {
-        if (functionResult.getThrowable() != null) {
-          throw functionResult.getThrowable();
-        }
-        if (functionResult.getMessage() != null) {
-          errorMessage = functionResult.getMessage();
-        } else {
-          errorMessage = "Destroy failed on one member";
+        if (xmlEntity.get() == null) {
+          xmlEntity.set(functionResult.getXmlEntity());
         }
-        // if any error occurred, break out without looking further
-        break;
+        tabularData.accumulate("Status", functionResult.getMessage());
+        regionDestroyed = true;
+      } else {
+        tabularData.accumulate("Status", "Error: " + 
functionResult.getErrorMessage());
       }
     }
 
-    if (errorMessage != null) {
-      return ResultBuilder.createGemFireErrorResult(errorMessage);
-    }
+    tabularData.setStatus(regionDestroyed ? Result.Status.OK : 
Result.Status.ERROR);
 
-    Result result =
-        ResultBuilder.createInfoResult(String.format("\"%s\" destroyed 
successfully.", regionPath));
-    if (xmlEntity.get() != null) {
+    CommandResult result = ResultBuilder.buildResult(tabularData);
+
+    // if at least one member returns with successful deletion, we will need 
to update cc
+    if (regionDestroyed) {
       persistClusterConfiguration(result,
           () -> getSharedConfiguration().deleteXmlEntity(xmlEntity.get(), 
null));
     }
     return result;
   }
+
 }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshCommand.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshCommand.java
index f94b6d1109..b251d64804 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshCommand.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/GfshCommand.java
@@ -15,6 +15,7 @@
 package org.apache.geode.management.internal.cli.commands;
 
 import java.util.Collections;
+import java.util.List;
 import java.util.Set;
 
 import org.springframework.shell.core.CommandMarker;
@@ -33,6 +34,7 @@
 import org.apache.geode.management.cli.Result;
 import org.apache.geode.management.internal.cli.CliUtil;
 import 
org.apache.geode.management.internal.cli.exceptions.EntityNotFoundException;
+import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.i18n.CliStrings;
 import org.apache.geode.management.internal.cli.shell.Gfsh;
 
@@ -180,6 +182,12 @@ default ManagementService getManagementService() {
     return executeFunction(function, args, 
Collections.singleton(targetMember));
   }
 
+  default List<CliFunctionResult> executeAndGetFunctionResult(Function 
function, Object args,
+      Set<DistributedMember> targetMembers) {
+    ResultCollector rc = executeFunction(function, args, targetMembers);
+    return CliFunctionResult.cleanResults((List<?>) rc.getResult());
+  }
+
   default Set<DistributedMember> findAnyMembersForRegion(InternalCache cache, 
String regionPath) {
     return CliUtil.getRegionAssociatedMembers(regionPath, cache, false);
   }
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionCreateFunction.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionCreateFunction.java
index 1c7baef4d1..80985660b7 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionCreateFunction.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionCreateFunction.java
@@ -74,8 +74,7 @@ public void execute(FunctionContext context) {
     ResultSender<Object> resultSender = context.getResultSender();
 
     Cache cache = context.getCache();
-    String memberNameOrId =
-        
CliUtil.getMemberNameOrId(cache.getDistributedSystem().getDistributedMember());
+    String memberNameOrId = context.getMemberName();
 
     RegionFunctionArgs regionCreateArgs = (RegionFunctionArgs) 
context.getArguments();
 
diff --git 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunction.java
 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunction.java
index 1aae3383a4..ef235223e9 100644
--- 
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunction.java
+++ 
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunction.java
@@ -16,10 +16,12 @@
 
 import org.apache.geode.cache.Cache;
 import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionDestroyedException;
 import org.apache.geode.cache.execute.Function;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.internal.InternalEntity;
 import org.apache.geode.internal.cache.xmlcache.CacheXml;
+import org.apache.geode.internal.logging.LogService;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
 
 /**
@@ -41,6 +43,8 @@ public boolean hasResult() {
   @Override
   public void execute(FunctionContext context) {
     String regionPath = null;
+    String memberName = context.getMemberName();
+
     try {
       String functionId = context.getFunctionId();
       Object arguments = context.getArguments();
@@ -54,24 +58,31 @@ public void execute(FunctionContext context) {
       regionPath = (String) arguments;
       Cache cache = context.getCache();
       Region<?, ?> region = cache.getRegion(regionPath);
-      // if the region is a distributed region, and is already destroyed by 
another member
+      // the region is already destroyed by another member
       if (region == null) {
-        context.getResultSender().lastResult(new CliFunctionResult("", true, 
"SUCCESS"));
+        context.getResultSender().lastResult(new CliFunctionResult(memberName, 
true,
+            String.format("Region '%s' already destroyed", regionPath)));
         return;
       }
 
       region.destroyRegion();
+
       String regionName =
           regionPath.startsWith(Region.SEPARATOR) ? regionPath.substring(1) : 
regionPath;
       XmlEntity xmlEntity = new XmlEntity(CacheXml.REGION, "name", regionName);
-      context.getResultSender().lastResult(new CliFunctionResult("", 
xmlEntity, regionPath));
+      context.getResultSender().lastResult(new CliFunctionResult(memberName, 
xmlEntity,
+          String.format("Region '%s' destroyed successfully", regionPath)));
 
     } catch (IllegalStateException ex) {
-      // user is trying to destroy something that can't destroyed.
-      context.getResultSender().lastResult(new CliFunctionResult("", false, 
ex.getMessage()));
-    } catch (Exception ex) {
+      // user is trying to destroy something that can't destroyed, like 
co-location
       context.getResultSender()
-          .lastResult(new CliFunctionResult("", ex, "failed to destroy " + 
regionPath));
+          .lastResult(new CliFunctionResult(memberName, false, 
ex.getMessage()));
+    } catch (RegionDestroyedException ex) {
+      context.getResultSender().lastResult(new CliFunctionResult(memberName, 
true,
+          String.format("Region '%s' already destroyed", regionPath)));
+    } catch (Exception ex) {
+      LogService.getLogger().error(ex.getMessage(), ex);
+      context.getResultSender().lastResult(new CliFunctionResult(memberName, 
ex, ex.getMessage()));
     }
   }
 
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommandTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommandTest.java
index 3fd59af89c..3073eaffa5 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommandTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/CreateAsyncEventQueueCommandTest.java
@@ -128,8 +128,8 @@ public void buildResult_all_success() throws Exception {
 
     // this is only to make the code pass that member check
     doReturn(Collections.emptySet()).when(command).getMembers(any(), any());
-    doReturn(functionResults).when(command).execute(isA(Function.class), 
isA(Object.class),
-        isA(Set.class));
+    
doReturn(functionResults).when(command).executeAndGetFunctionResult(isA(Function.class),
+        isA(Object.class), isA(Set.class));
 
     gfsh.executeAndAssertThat(command, 
MINIUM_COMMAND).statusIsSuccess().persisted()
         .tableHasRowCount("Member", 2)
@@ -151,8 +151,8 @@ public void buildResult_all_failure() throws Exception {
 
     // this is only to make the code pass that member check
     doReturn(Collections.emptySet()).when(command).getMembers(any(), any());
-    doReturn(functionResults).when(command).execute(isA(Function.class), 
isA(Object.class),
-        isA(Set.class));
+    
doReturn(functionResults).when(command).executeAndGetFunctionResult(isA(Function.class),
+        isA(Object.class), isA(Set.class));
 
     gfsh.executeAndAssertThat(command, 
MINIUM_COMMAND).statusIsSuccess().persisted() // need to make
                                                                                
      // sure
@@ -182,8 +182,8 @@ public void buildResult_one_failure_one_success() throws 
Exception {
 
     // this is only to make the code pass that member check
     doReturn(Collections.emptySet()).when(command).getMembers(any(), any());
-    doReturn(functionResults).when(command).execute(isA(Function.class), 
isA(Object.class),
-        isA(Set.class));
+    
doReturn(functionResults).when(command).executeAndGetFunctionResult(isA(Function.class),
+        isA(Object.class), isA(Set.class));
 
     gfsh.executeAndAssertThat(command, 
MINIUM_COMMAND).statusIsSuccess().persisted()
         .tableHasRowCount("Member", 2)
@@ -202,8 +202,8 @@ public void 
command_succeeded_but_no_cluster_config_service() throws Exception {
     List<CliFunctionResult> functionResults = new ArrayList<>();
     XmlEntity xmlEntity = mock(XmlEntity.class);
     functionResults.add(new CliFunctionResult("member1", xmlEntity, 
"SUCCESS"));
-    doReturn(functionResults).when(command).execute(isA(Function.class), 
isA(Object.class),
-        isA(Set.class));
+    
doReturn(functionResults).when(command).executeAndGetFunctionResult(isA(Function.class),
+        isA(Object.class), isA(Set.class));
 
     gfsh.executeAndAssertThat(command, 
MINIUM_COMMAND).statusIsSuccess().failToPersist();
 
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandDUnitTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandDUnitTest.java
index 51e2102b08..55dbff3e6c 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandDUnitTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandDUnitTest.java
@@ -27,13 +27,10 @@
 import org.junit.experimental.categories.Category;
 
 import org.apache.geode.cache.Cache;
-import org.apache.geode.cache.PartitionAttributesFactory;
-import org.apache.geode.cache.RegionFactory;
-import org.apache.geode.cache.RegionShortcut;
-import org.apache.geode.cache.Scope;
 import org.apache.geode.distributed.Locator;
 import org.apache.geode.distributed.internal.ClusterConfigurationService;
 import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.management.internal.configuration.domain.Configuration;
 import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
 import org.apache.geode.test.dunit.rules.MemberVM;
 import org.apache.geode.test.junit.categories.DistributedTest;
@@ -52,7 +49,7 @@
   @BeforeClass
   public static void beforeClass() throws Exception {
     locator = lsRule.startLocatorVM(0);
-    server1 = lsRule.startServerVM(1, locator.getPort());
+    server1 = lsRule.startServerVM(1, "group1", locator.getPort());
     server2 = lsRule.startServerVM(2, locator.getPort());
     server3 = lsRule.startServerVM(3, locator.getPort());
   }
@@ -64,91 +61,84 @@ public void before() throws Exception {
 
   @Test
   public void testDestroyDistributedRegion() {
-    MemberVM.invokeInEveryMember(() -> {
-      Cache cache = LocatorServerStartupRule.getCache();
-      RegionFactory<Object, Object> factory = 
cache.createRegionFactory(RegionShortcut.PARTITION);
-      factory.create("Customer");
+    gfsh.executeAndAssertThat("create region --name=Customer 
--type=PARTITION").statusIsSuccess();
+    gfsh.executeAndAssertThat(
+        "create region --name=Order --type=PARTITION 
--colocated-with=Customer").statusIsSuccess();
 
-      PartitionAttributesFactory paFactory = new PartitionAttributesFactory();
-      paFactory.setColocatedWith("Customer");
-      factory.setPartitionAttributes(paFactory.create());
-      factory.create("Order");
-    }, server1, server2);
-
-    locator.waitTillRegionsAreReadyOnServers("/Customer", 2);
-    locator.waitTillRegionsAreReadyOnServers("/Order", 2);
+    locator.waitTillRegionsAreReadyOnServers("/Customer", 3);
+    locator.waitTillRegionsAreReadyOnServers("/Order", 3);
 
     // Test unable to destroy with co-location
     gfsh.executeAndAssertThat("destroy region 
--name=/Customer").statusIsError()
+        .tableHasRowCount("Member", 3)
         .containsOutput("The parent region [/Customer] in colocation chain 
cannot be destroyed");
 
     // Test success
     gfsh.executeAndAssertThat("destroy region --name=/Order").statusIsSuccess()
-        .containsOutput("destroyed successfully");
+        .tableHasRowCount("Member", 3).containsOutput("destroyed 
successfully");
     gfsh.executeAndAssertThat("destroy region 
--name=/Customer").statusIsSuccess()
-        .containsOutput("destroyed successfully");
+        .tableHasRowCount("Member", 3).containsOutput("destroyed 
successfully");
 
     // destroy something that's not exist anymore
     gfsh.executeAndAssertThat("destroy region 
--name=/Customer").statusIsError()
         .containsOutput("Could not find a Region");
-    gfsh.executeAndAssertThat("destroy region --name=/Customer 
--if-exists").statusIsSuccess();
+    gfsh.executeAndAssertThat("destroy region --name=/Customer --if-exists")
+        .containsOutput("Skipping: Could not find a Region").statusIsSuccess();
   }
 
   @Test
   public void testDestroyLocalRegions() {
-    MemberVM.invokeInEveryMember(() -> {
-      Cache cache = LocatorServerStartupRule.getCache();
-      RegionFactory<Object, Object> factory = 
cache.createRegionFactory(RegionShortcut.REPLICATE);
-      factory.setScope(Scope.LOCAL);
-      factory.create("Customer");
-    }, server1, server2, server3);
+    gfsh.executeAndAssertThat("create region --name=region1 
--type=LOCAL").statusIsSuccess();
 
-    locator.waitTillRegionsAreReadyOnServers("/Customer", 3);
+    locator.waitTillRegionsAreReadyOnServers("/region1", 3);
 
-    gfsh.executeAndAssertThat("destroy region 
--name=Customer").statusIsSuccess()
-        .containsOutput("destroyed successfully");
+    gfsh.executeAndAssertThat("destroy region 
--name=region1").statusIsSuccess()
+        .tableHasRowCount("Member", 3).containsOutput("destroyed 
successfully");
 
     MemberVM.invokeInEveryMember(() -> {
       Cache cache = LocatorServerStartupRule.getCache();
-      assertThat(cache.getRegion("Customer")).isNull();
+      assertThat(cache.getRegion("region1")).isNull();
     }, server1, server2, server3);
   }
 
   @Test
   public void testDestroyLocalAndDistributedRegions() {
-    MemberVM.invokeInEveryMember(() -> {
-      Cache cache = LocatorServerStartupRule.getCache();
-      RegionFactory<Object, Object> factory = 
cache.createRegionFactory(RegionShortcut.PARTITION);
-      factory.create("Customer");
-      factory.create("Customer_2");
-      factory.create("Customer_3");
-    }, server1, server2);
+    gfsh.executeAndAssertThat("create region --name=region1 --type=LOCAL 
--group=group1")
+        .statusIsSuccess();
+    gfsh.executeAndAssertThat("create region --name=region1 
--type=REPLICATE").statusIsSuccess();
 
-    server3.invoke(() -> {
-      Cache cache = LocatorServerStartupRule.getCache();
-      RegionFactory<Object, Object> factory = 
cache.createRegionFactory(RegionShortcut.REPLICATE);
-      factory.setScope(Scope.LOCAL);
-      factory.create("Customer");
-      factory.create("Customer_2");
-      factory.create("Customer_3");
+    locator.waitTillRegionsAreReadyOnServers("/region1", 3);
+
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration group1Config = service.getConfiguration("group1");
+      assertThat(group1Config.getCacheXmlContent())
+          .contains("<region name=\"region1\">\n" + "    <region-attributes 
scope=\"local\"/>");
+
+      Configuration clusterConfig = service.getConfiguration("cluster");
+      assertThat(clusterConfig.getCacheXmlContent()).contains("<region 
name=\"region1\">\n"
+          + "    <region-attributes data-policy=\"replicate\" 
scope=\"distributed-ack\"/>");
     });
 
-    locator.waitTillRegionsAreReadyOnServers("/Customer", 3);
-    locator.waitTillRegionsAreReadyOnServers("/Customer_2", 3);
-    locator.waitTillRegionsAreReadyOnServers("/Customer_3", 3);
+    gfsh.executeAndAssertThat("destroy region 
--name=region1").statusIsSuccess()
+        .tableHasRowCount("Member", 3).containsOutput("destroyed 
successfully");
 
-    gfsh.executeAndAssertThat("destroy region 
--name=Customer").statusIsSuccess()
-        .containsOutput("destroyed successfully");
-    gfsh.executeAndAssertThat("destroy region 
--name=Customer_2").statusIsSuccess()
-        .containsOutput("destroyed successfully");
-    gfsh.executeAndAssertThat("destroy region 
--name=Customer_3").statusIsSuccess()
-        .containsOutput("destroyed successfully");
+    // verify that all cc entries are deleted, no matter what the scope is
+    locator.invoke(() -> {
+      ClusterConfigurationService service =
+          LocatorServerStartupRule.getLocator().getSharedConfiguration();
+      Configuration group1Config = service.getConfiguration("group1");
+      assertThat(group1Config.getCacheXmlContent()).doesNotContain("region1");
 
+      Configuration clusterConfig = service.getConfiguration("cluster");
+      assertThat(clusterConfig.getCacheXmlContent()).doesNotContain("region1");
+    });
+
+    // verify that all regions are destroyed, no matter what the scope is
     MemberVM.invokeInEveryMember(() -> {
       Cache cache = LocatorServerStartupRule.getCache();
-      assertThat(cache.getRegion("Customer")).isNull();
-      assertThat(cache.getRegion("Customer_2")).isNull();
-      assertThat(cache.getRegion("Customer_3")).isNull();
+      assertThat(cache.getRegion("region1")).isNull();
     }, server1, server2, server3);
   }
 
@@ -156,20 +146,14 @@ public void testDestroyLocalAndDistributedRegions() {
   public void testDestroyRegionWithSharedConfig() throws IOException {
     gfsh.executeAndAssertThat("create region --name=Customer 
--type=REPLICATE").statusIsSuccess();
 
+    // Make sure the region exists in the cluster config
     locator.invoke(() -> {
-      // Make sure the region exists in the cluster config
       ClusterConfigurationService sharedConfig =
           ((InternalLocator) Locator.getLocator()).getSharedConfiguration();
       assertThat(sharedConfig.getConfiguration("cluster").getCacheXmlContent())
           .contains("Customer");
     });
 
-    // make sure region does exists
-    MemberVM.invokeInEveryMember(() -> {
-      Cache cache = LocatorServerStartupRule.getCache();
-      assertThat(cache.getRegion("Customer")).isNotNull();
-    }, server1, server2, server3);
-
     // destroy the region
     gfsh.executeAndAssertThat("destroy region 
--name=Customer").statusIsSuccess()
         .containsOutput("destroyed successfully");
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandTest.java
index 12f43efee0..374ec2a9da 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/DestroyRegionCommandTest.java
@@ -15,6 +15,7 @@
 
 package org.apache.geode.management.internal.cli.commands;
 
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -33,9 +34,10 @@
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
 
-import org.apache.geode.cache.execute.ResultCollector;
 import org.apache.geode.distributed.DistributedMember;
+import org.apache.geode.distributed.internal.ClusterConfigurationService;
 import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.management.internal.cli.GfshParseResult;
 import org.apache.geode.management.internal.cli.functions.CliFunctionResult;
 import org.apache.geode.management.internal.cli.result.CommandResult;
 import org.apache.geode.management.internal.configuration.domain.XmlEntity;
@@ -51,19 +53,24 @@
   private DestroyRegionCommand command;
   private CommandResult result;
   private CliFunctionResult result1, result2;
+  private ClusterConfigurationService ccService;
+  XmlEntity xmlEntity;
 
   @Before
   public void before() throws Exception {
+    xmlEntity = mock(XmlEntity.class);
     command = spy(DestroyRegionCommand.class);
+    ccService = mock(ClusterConfigurationService.class);
+    doReturn(ccService).when(command).getSharedConfiguration();
     doReturn(mock(InternalCache.class)).when(command).getCache();
 
-    ResultCollector collector = mock(ResultCollector.class);
-    doReturn(collector).when(command).executeFunction(any(), any(), 
any(Set.class));
-
     List<CliFunctionResult> functionResults = new ArrayList<>();
-    doReturn(functionResults).when(collector).getResult();
+    doReturn(functionResults).when(command).executeAndGetFunctionResult(any(), 
any(),
+        any(Set.class));
     result1 = mock(CliFunctionResult.class);
     result2 = mock(CliFunctionResult.class);
+    when(result1.getMemberIdOrName()).thenReturn("member1");
+    when(result2.getMemberIdOrName()).thenReturn("member2");
     functionResults.add(result1);
     functionResults.add(result2);
   }
@@ -80,6 +87,12 @@ public void invalidRegion() throws Exception {
         .containsOutput("Invalid command");
   }
 
+  @Test
+  public void regionConverterApplied() {
+    GfshParseResult parseResult = parser.parse("destroy region --name=test");
+    assertThat(parseResult.getParamValue("name")).isEqualTo("/test");
+  }
+
   @Test
   public void whenNoRegionIsFoundOnAnyMembers() throws Exception {
     doReturn(Collections.emptySet()).when(command).findMembersForRegion(any(), 
any());
@@ -91,41 +104,60 @@ public void whenNoRegionIsFoundOnAnyMembers() throws 
Exception {
   }
 
   @Test
-  public void multipleResultReturnedWithOneError() throws Exception {
+  public void multipleResultReturned_oneSucess_oneFailed() throws Exception {
     // mock this to pass the member search call
     doReturn(Collections.singleton(DistributedMember.class)).when(command)
         .findMembersForRegion(any(), any());
     when(result1.isSuccessful()).thenReturn(true);
     when(result1.getMessage()).thenReturn("result1 message");
-    when(result1.getXmlEntity()).thenReturn(mock(XmlEntity.class));
+    when(result1.getXmlEntity()).thenReturn(xmlEntity);
 
     when(result2.isSuccessful()).thenReturn(false);
-    when(result2.getMessage()).thenReturn("result2 message");
+    when(result2.getErrorMessage()).thenReturn("result2 message");
 
-    parser.executeAndAssertThat(command, "destroy region 
--name=test").statusIsError()
-        .containsOutput("result2 message");
+    parser.executeAndAssertThat(command, "destroy region 
--name=test").statusIsSuccess()
+        .containsOutput("result1 message").containsOutput("result2 message");
 
-    // verify that xmlEntiry returned by the result1 is not saved to Cluster 
config
-    verify(command, never()).persistClusterConfiguration(any(), any());
+    // verify that xmlEntiry returned by the result1 is saved to Cluster config
+    verify(ccService).deleteXmlEntity(xmlEntity, null);
   }
 
   @Test
-  public void multipleResultReturnedWithOneException() throws Exception {
+  public void multipleResultReturned_oneSuccess_oneException() throws 
Exception {
     // mock this to pass the member search call
     doReturn(Collections.singleton(DistributedMember.class)).when(command)
         .findMembersForRegion(any(), any());
     when(result1.isSuccessful()).thenReturn(true);
     when(result1.getMessage()).thenReturn("result1 message");
-    when(result1.getXmlEntity()).thenReturn(mock(XmlEntity.class));
+    when(result1.getXmlEntity()).thenReturn(xmlEntity);
+
+    when(result2.isSuccessful()).thenReturn(false);
+    when(result2.getErrorMessage()).thenReturn("something happened");
+
+    parser.executeAndAssertThat(command, "destroy region 
--name=test").statusIsSuccess()
+        .containsOutput("result1 message").containsOutput("something 
happened");
+
+
+    // verify that xmlEntiry returned by the result1 is saved to Cluster config
+    verify(ccService).deleteXmlEntity(xmlEntity, null);
+  }
+
+  @Test
+  public void multipleResultReturned_all_failed() throws Exception {
+    // mock this to pass the member search call
+    doReturn(Collections.singleton(DistributedMember.class)).when(command)
+        .findMembersForRegion(any(), any());
+    when(result1.isSuccessful()).thenReturn(false);
+    when(result1.getErrorMessage()).thenReturn("result1 message");
 
     when(result2.isSuccessful()).thenReturn(false);
-    when(result2.getThrowable()).thenReturn(new 
IllegalArgumentException("something happened"));
+    when(result2.getErrorMessage()).thenReturn("something happened");
 
     parser.executeAndAssertThat(command, "destroy region 
--name=test").statusIsError()
-        .containsOutput("something happened");
+        .containsOutput("result1 message").containsOutput("something 
happened");
 
 
-    // verify that xmlEntiry returned by the result1 is not saved to Cluster 
config
+    // verify that xmlEntiry returned by the result1 is saved to Cluster config
     verify(command, never()).persistClusterConfiguration(any(), any());
   }
 }
diff --git 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunctionTest.java
 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunctionTest.java
index 60885099b2..31f3b12d15 100644
--- 
a/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunctionTest.java
+++ 
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/functions/RegionDestroyFunctionTest.java
@@ -29,6 +29,7 @@
 import org.mockito.ArgumentCaptor;
 
 import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionDestroyedException;
 import org.apache.geode.cache.execute.FunctionContext;
 import org.apache.geode.cache.execute.ResultSender;
 import org.apache.geode.internal.cache.InternalCache;
@@ -76,7 +77,24 @@ public void regionAlreadyDestroyed() throws Exception {
     CliFunctionResult result = resultCaptor.getValue();
 
     assertThat(result.isSuccessful()).isTrue();
-    assertThat(result.getMessage()).contains("SUCCESS");
+    assertThat(result.getThrowable()).isNull();
+    assertThat(result.getMessage()).contains("Region 'testRegion' already 
destroyed");
+  }
+
+  @Test
+  public void regionAlreadyDestroyed_throwException() throws Exception {
+    
when(context.getFunctionId()).thenReturn(RegionDestroyFunction.class.getName());
+    Region region = mock(Region.class);
+    when(cache.getRegion(any())).thenReturn(region);
+    doThrow(mock(RegionDestroyedException.class)).when(region).destroyRegion();
+    function.execute(context);
+
+    verify(resultSender).lastResult(resultCaptor.capture());
+    CliFunctionResult result = resultCaptor.getValue();
+
+    assertThat(result.isSuccessful()).isTrue();
+    assertThat(result.getThrowable()).isNull();
+    assertThat(result.getMessage()).contains("Region 'testRegion' already 
destroyed");
   }
 
   @Test


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


> Command that executes function on multiple members should report the status 
> of execution on each member
> -------------------------------------------------------------------------------------------------------
>
>                 Key: GEODE-4049
>                 URL: https://issues.apache.org/jira/browse/GEODE-4049
>             Project: Geode
>          Issue Type: Bug
>            Reporter: Jinmei Liao
>
> "destroy region", even though executes function on multiple members, do not 
> report the result as tabular results. Need to change that.
> The tabular results of these commands should be successful if at least one 
> member executes successfully. Cluster config should be updated if one 
> function gets executed successfully.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to