geode-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jinmeil...@apache.org
Subject [geode] branch develop updated: GEODE-3788: add alter async-event-queue command and tests
Date Wed, 29 Nov 2017 05:07:19 GMT
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 e057702  GEODE-3788: add alter async-event-queue command and tests
e057702 is described below

commit e0577021b6a35a2c030693ba11d10322aaafcee1
Author: Jinmei Liao <jiliao@pivotal.io>
AuthorDate: Thu Nov 16 10:12:01 2017 -0800

    GEODE-3788: add alter async-event-queue command and tests
---
 .../internal/ClusterConfigurationService.java      |  12 +-
 .../cli/commands/AlterAsyncEventQueueCommand.java  | 168 +++++++++++++++
 .../ExportImportClusterConfigurationCommands.java  |   4 +-
 .../management/internal/cli/json/GfJsonObject.java |   3 +
 .../internal/cli/result/TabularResultData.java     |  18 ++
 .../AlterAsyncEventQueueCommandDUnitTest.java      | 100 +++++++++
 .../commands/AlterAsyncEventQueueCommandTest.java  | 239 +++++++++++++++++++++
 .../internal/cli/result/TabularResultDataTest.java |  51 +++++
 .../internal/configuration/ClusterConfig.java      |   2 +-
 9 files changed, 585 insertions(+), 12 deletions(-)

diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/ClusterConfigurationService.java
b/geode-core/src/main/java/org/apache/geode/distributed/internal/ClusterConfigurationService.java
index 6640bac..16b86aa 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/ClusterConfigurationService.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/ClusterConfigurationService.java
@@ -559,11 +559,6 @@ public class ClusterConfigurationService {
     return getConfigurationRegion().get(groupName);
   }
 
-  public Map<String, Configuration> getEntireConfiguration() {
-    Set<String> keys = getConfigurationRegion().keySet();
-    return getConfigurationRegion().getAll(keys);
-  }
-
   /**
    * Returns the path of Shared configuration directory
    *
@@ -653,12 +648,11 @@ public class ClusterConfigurationService {
     FileUtils.writeStringToFile(xmlFile, configuration.getCacheXmlContent(), "UTF-8");
   }
 
-  // TODO: return value is never used
-  private boolean lockSharedConfiguration() {
+  public boolean lockSharedConfiguration() {
     return this.sharedConfigLockingService.lock(SHARED_CONFIG_LOCK_NAME, -1, -1);
   }
 
-  private void unlockSharedConfiguration() {
+  public void unlockSharedConfiguration() {
     this.sharedConfigLockingService.unlock(SHARED_CONFIG_LOCK_NAME);
   }
 
@@ -681,7 +675,7 @@ public class ClusterConfigurationService {
    *
    * @return {@link Region} ConfigurationRegion, this should never be null
    */
-  private Region<String, Configuration> getConfigurationRegion() {
+  public Region<String, Configuration> getConfigurationRegion() {
     Region<String, Configuration> configRegion = this.cache.getRegion(CONFIG_REGION_NAME);
 
     try {
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommand.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommand.java
new file mode 100644
index 0000000..42f0079
--- /dev/null
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommand.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version
2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain
a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express
+ * or implied. See the License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.commands;
+
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.CREATE_ASYNC_EVENT_QUEUE__BATCHTIMEINTERVAL__HELP;
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.CREATE_ASYNC_EVENT_QUEUE__BATCH_SIZE__HELP;
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.CREATE_ASYNC_EVENT_QUEUE__MAXIMUM_QUEUE_MEMORY__HELP;
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.IFEXISTS;
+import static org.apache.geode.management.internal.cli.i18n.CliStrings.IFEXISTS_HELP;
+
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.springframework.shell.core.annotation.CliCommand;
+import org.springframework.shell.core.annotation.CliOption;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.distributed.internal.ClusterConfigurationService;
+import org.apache.geode.management.cli.CliMetaData;
+import org.apache.geode.management.cli.Result;
+import org.apache.geode.management.internal.cli.AbstractCliAroundInterceptor;
+import org.apache.geode.management.internal.cli.GfshParseResult;
+import org.apache.geode.management.internal.cli.exceptions.EntityNotFoundException;
+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.Configuration;
+import org.apache.geode.management.internal.configuration.utils.XmlUtils;
+import org.apache.geode.management.internal.security.ResourceOperation;
+import org.apache.geode.security.ResourcePermission;
+
+/**
+ * this command currently only updates the cluster configuration. Requires server restart
to pick up
+ * the changes.
+ */
+public class AlterAsyncEventQueueCommand implements GfshCommand {
+
+  static final String COMMAND_NAME = "alter async-event-queue";
+  static final String ID = "id";
+  static final String BATCH_SIZE = "batch-size";
+  static final String BATCH_TIME_INTERVAL = "batch-time-interval";
+  static final String MAX_QUEUE_MEMORY = "max-queue-memory";
+  static final String MAXIMUM_QUEUE_MEMORY = "maximum-queue-memory";
+
+  static final String COMMAND_HELP =
+      "alter attributes of async-event-queue, needs rolling restart for new attributes to
take effect. ";
+  static final String ID_HELP = "Id of the async event queue to be changed.";
+  static final String BATCH_SIZE_HELP = CREATE_ASYNC_EVENT_QUEUE__BATCH_SIZE__HELP;
+  static final String BATCH_TIME_INTERVAL_HELP = CREATE_ASYNC_EVENT_QUEUE__BATCHTIMEINTERVAL__HELP;
+  static final String MAXIMUM_QUEUE_MEMORY_HELP =
+      CREATE_ASYNC_EVENT_QUEUE__MAXIMUM_QUEUE_MEMORY__HELP;
+
+
+  @CliCommand(value = COMMAND_NAME, help = COMMAND_HELP)
+  @CliMetaData(
+      interceptor = "org.apache.geode.management.internal.cli.commands.AlterAsyncEventQueueCommand$Interceptor")
+  @ResourceOperation(resource = ResourcePermission.Resource.CLUSTER,
+      operation = ResourcePermission.Operation.MANAGE, target = ResourcePermission.Target.DEPLOY)
+  public Result execute(@CliOption(key = ID, mandatory = true, help = ID_HELP) String id,
+      @CliOption(key = BATCH_SIZE, help = BATCH_SIZE_HELP) Integer batchSize,
+      @CliOption(key = BATCH_TIME_INTERVAL,
+          help = BATCH_TIME_INTERVAL_HELP) Integer batchTimeInterval,
+      @CliOption(key = MAX_QUEUE_MEMORY, help = MAXIMUM_QUEUE_MEMORY_HELP) Integer maxQueueMemory,
+      @CliOption(key = IFEXISTS, help = IFEXISTS_HELP, specifiedDefaultValue = "true",
+          unspecifiedDefaultValue = "false") boolean ifExists)
+      throws IOException, SAXException, ParserConfigurationException, TransformerException
{
+
+    // need not check if any running servers has this async-event-queue. A server with this
queue id
+    // may be shutdown, but we still need to update Cluster Configuration.
+    ClusterConfigurationService service = getSharedConfiguration();
+
+    boolean locked = service.lockSharedConfiguration();
+    if (!locked) {
+      return ResultBuilder.createGemFireErrorResult("Unable to lock the cluster configuration.");
+    }
+
+    TabularResultData tableData = ResultBuilder.createTabularResultData();
+    try {
+      Region<String, Configuration> configRegion = service.getConfigurationRegion();
+      for (String group : configRegion.keySet()) {
+        Configuration config = configRegion.get(group);
+        if (config.getCacheXmlContent() == null) {
+          // skip to the next group
+          continue;
+        }
+
+        boolean xmlUpdated = false;
+        Document document = XmlUtils.createDocumentFromXml(config.getCacheXmlContent());
+        NodeList nodeList = document.getElementsByTagName("async-event-queue");
+        for (int i = 0; i < nodeList.getLength(); i++) {
+          Element item = (Element) nodeList.item(i);
+          String queueId = item.getAttribute("id");
+          if (!id.equals(queueId)) {
+            // skip to the next async-event-queue found in this xml
+            continue;
+          }
+          // this node is the async-event-queue with the correct id
+          if (batchSize != null) {
+            item.setAttribute(BATCH_SIZE, batchSize + "");
+          }
+          if (batchTimeInterval != null) {
+            item.setAttribute(BATCH_TIME_INTERVAL, batchTimeInterval + "");
+          }
+          if (maxQueueMemory != null) {
+            item.setAttribute(MAXIMUM_QUEUE_MEMORY, maxQueueMemory + "");
+          }
+          // each group should have only one queue with this id defined
+          tableData.accumulate("Group", group);
+          tableData.accumulate("Status", "Cluster Configuration Updated");
+          xmlUpdated = true;
+          break;
+        }
+
+        if (xmlUpdated) {
+          String newXml = XmlUtils.prettyXml(document.getFirstChild());
+          config.setCacheXmlContent(newXml);
+          configRegion.put(group, config);
+        }
+      }
+    } finally {
+      service.unlockSharedConfiguration();
+    }
+
+    if (tableData.rowSize("Group") == 0) {
+      String message = String.format("Can not find an async event queue with id '%s'.", id);
+      throw new EntityNotFoundException(message, ifExists);
+    }
+
+    // some configurations are changed, print out the warning message as well.
+    tableData.setFooter(System.lineSeparator()
+        + "These changes won't take effect on the running servers. " + System.lineSeparator()
+        + "Please restart the servers in these groups for the changes to take effect.");
+    return ResultBuilder.buildResult(tableData);
+  }
+
+  public static class Interceptor extends AbstractCliAroundInterceptor {
+    @Override
+    public Result preExecution(GfshParseResult parseResult) {
+      Object batchSize = parseResult.getParamValue(BATCH_SIZE);
+      Object batchTimeInterval = parseResult.getParamValue(BATCH_TIME_INTERVAL);
+      Object maxQueueMemory = parseResult.getParamValue(MAX_QUEUE_MEMORY);
+
+      if (batchSize == null && batchTimeInterval == null && maxQueueMemory
== null) {
+        return ResultBuilder
+            .createUserErrorResult("need to specify at least one option to modify.");
+      }
+      return ResultBuilder.createInfoResult("");
+    }
+  }
+}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
index 89e452d..e85c1ae 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ExportImportClusterConfigurationCommands.java
@@ -96,7 +96,7 @@ public class ExportImportClusterConfigurationCommands implements GfshCommand
{
 
     Result result;
     try {
-      for (Configuration config : sc.getEntireConfiguration().values()) {
+      for (Configuration config : sc.getConfigurationRegion().values()) {
         sc.writeConfigToFile(config);
       }
       ZipUtils.zipDirectory(sc.getSharedConfigurationDirPath(), zipFile.getCanonicalPath());
@@ -162,7 +162,7 @@ public class ExportImportClusterConfigurationCommands implements GfshCommand
{
       ClusterConfigurationService sc = locator.getSharedConfiguration();
 
       // backup the old config
-      for (Configuration config : sc.getEntireConfiguration().values()) {
+      for (Configuration config : sc.getConfigurationRegion().values()) {
         sc.writeConfigToFile(config);
       }
       sc.renameExistingSharedConfigDirectory();
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
index 0000ec5..3326118 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/json/GfJsonObject.java
@@ -305,6 +305,9 @@ public class GfJsonObject {
     return jsonObject.keys();
   }
 
+  /**
+   * @return the column size of this GfJsonObject
+   */
   public int size() {
     return jsonObject.length();
   }
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
index c694a8b..92e3261 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/result/TabularResultData.java
@@ -51,6 +51,24 @@ public class TabularResultData extends AbstractResultData {
     return null;
   }
 
+  public int columnSize() {
+    return contentObject.size();
+  }
+
+  public int rowSize(String key) {
+    GfJsonArray jsonArray = null;
+    try {
+      jsonArray = contentObject.getJSONArray(key);
+    } catch (GfJsonException e) {
+      throw new RuntimeException("unable to get the row size of " + key);
+    }
+    if (jsonArray == null) {
+      return 0;
+    }
+
+    return jsonArray.getInternalJsonArray().length();
+  }
+
   /**
    * @return the gfJsonObject
    */
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommandDUnitTest.java
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommandDUnitTest.java
new file mode 100644
index 0000000..daf36be
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommandDUnitTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version
2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain
a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express
+ * or implied. See the License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.commands;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.asyncqueue.AsyncEventQueue;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.internal.cache.wan.MyAsyncEventListener;
+import org.apache.geode.test.dunit.rules.LocatorServerStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.categories.AcceptanceTest;
+import org.apache.geode.test.junit.rules.GfshCommandRule;
+
+
+@Category(AcceptanceTest.class)
+public class AlterAsyncEventQueueCommandDUnitTest {
+
+  @Rule
+  public LocatorServerStartupRule lsRule = new LocatorServerStartupRule();
+
+  @Rule
+  public GfshCommandRule gfsh = new GfshCommandRule();
+
+  private static MemberVM locator, server1, server2;
+
+  @Before
+  public void beforeClass() throws Exception {
+    locator = lsRule.startLocatorVM(0);
+    server1 = lsRule.startServerVM(1, "group1", locator.getPort());
+    gfsh.connectAndVerify(locator);
+  }
+
+
+
+  @Test
+  public void testAlterAsyncEventQueue() throws Exception {
+    gfsh.executeAndAssertThat("create async-event-queue --id=queue1 --group=group1 --listener="
+        + MyAsyncEventListener.class.getName()).statusIsSuccess();
+
+    locator.waitTillAsyncEventQueuesAreReadyOnServers("queue1", 1);
+
+    // verify that server1's event queue has the default value
+    server1.invoke(() -> {
+      InternalCache cache = LocatorServerStartupRule.getCache();
+      AsyncEventQueue queue = cache.getAsyncEventQueue("queue1");
+      assertThat(queue.getBatchSize()).isEqualTo(100);
+      assertThat(queue.getBatchTimeInterval()).isEqualTo(1000);
+      assertThat(queue.getMaximumQueueMemory()).isEqualTo(100);
+    });
+
+    gfsh.executeAndAssertThat("alter async-event-queue --id=queue1 " + "--batch-size=200
"
+        + "--batch-time-interval=300 " + "--max-queue-memory=400").statusIsSuccess();
+
+    // verify that server1's event queue still has the default value
+    // without restart
+    server1.invoke(() -> {
+      InternalCache cache = LocatorServerStartupRule.getCache();
+      AsyncEventQueue queue = cache.getAsyncEventQueue("queue1");
+      assertThat(queue.getBatchSize()).isEqualTo(100);
+      assertThat(queue.getBatchTimeInterval()).isEqualTo(1000);
+      assertThat(queue.getMaximumQueueMemory()).isEqualTo(100);
+      assertThat(cache.getAsyncEventQueue("queue2")).isNull();
+    });
+
+    // restart locator and server without clearing the file system
+    lsRule.stopVM(1, false);
+    lsRule.stopVM(0, false);
+
+    locator = lsRule.startLocatorVM(0);
+    server1 = lsRule.startServerVM(1, "group1", locator.getPort());
+    // verify that server1's queue is updated
+    server1.invoke(() -> {
+      InternalCache cache = LocatorServerStartupRule.getCache();
+      AsyncEventQueue queue = cache.getAsyncEventQueue("queue1");
+      assertThat(queue.getBatchSize()).isEqualTo(200);
+      assertThat(queue.getBatchTimeInterval()).isEqualTo(300);
+      assertThat(queue.getMaximumQueueMemory()).isEqualTo(400);
+      assertThat(cache.getAsyncEventQueue("queue2")).isNull();
+    });
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommandTest.java
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommandTest.java
new file mode 100644
index 0000000..38dc072
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/commands/AlterAsyncEventQueueCommandTest.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version
2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain
a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express
+ * or implied. See the License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.commands;
+
+import static org.apache.geode.management.internal.cli.commands.AlterAsyncEventQueueCommand.BATCH_SIZE;
+import static org.apache.geode.management.internal.cli.commands.AlterAsyncEventQueueCommand.BATCH_TIME_INTERVAL;
+import static org.apache.geode.management.internal.cli.commands.AlterAsyncEventQueueCommand.ID;
+import static org.apache.geode.management.internal.cli.commands.AlterAsyncEventQueueCommand.MAXIMUM_QUEUE_MEMORY;
+import static org.apache.geode.management.internal.cli.commands.AlterAsyncEventQueueCommand.MAX_QUEUE_MEMORY;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import org.apache.geode.cache.Region;
+import org.apache.geode.distributed.internal.ClusterConfigurationService;
+import org.apache.geode.management.internal.configuration.domain.Configuration;
+import org.apache.geode.management.internal.configuration.utils.XmlUtils;
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.apache.geode.test.junit.rules.GfshParserRule;
+
+
+@Category(UnitTest.class)
+public class AlterAsyncEventQueueCommandTest {
+
+  @ClassRule
+  public static GfshParserRule gfsh = new GfshParserRule();
+
+  private AlterAsyncEventQueueCommand command;
+  private ClusterConfigurationService service;
+  private Region<String, Configuration> configRegion;
+
+  @Before
+  public void before() throws Exception {
+    command = spy(AlterAsyncEventQueueCommand.class);
+    service = mock(ClusterConfigurationService.class);
+    doReturn(service).when(command).getSharedConfiguration();
+    configRegion = mock(Region.class);
+    when(service.getConfigurationRegion()).thenReturn(configRegion);
+    when(service.lockSharedConfiguration()).thenReturn(true);
+
+    when(configRegion.keySet())
+        .thenReturn(Arrays.stream("group1,group2".split(",")).collect(Collectors.toSet()));
+    Configuration configuration1 = new Configuration("group1");
+    configuration1.setCacheXmlContent(getCacheXml("queue1"));
+    when(configRegion.get("group1")).thenReturn(configuration1);
+
+    Configuration configuration2 = new Configuration("group2");
+    configuration2.setCacheXmlContent(getCacheXml("queue2"));
+    when(configRegion.get("group2")).thenReturn(configuration2);
+
+  }
+
+  @Test
+  public void mandatoryOption() throws Exception {
+    gfsh.executeAndAssertThat(command, "alter async-event-queue").statusIsError()
+        .containsOutput("Invalid command");
+  }
+
+  @Test
+  public void noOptionToModify() throws Exception {
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --id=test").statusIsError()
+        .containsOutput("need to specify at least one option to modify.");
+  }
+
+  @Test
+  public void emptyConfiguration() throws Exception {
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --id=test --batch-size=100")
+        .statusIsError().containsOutput("Can not find an async event queue");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  @Test
+  public void emptyConfiguration_ifExists() throws Exception {
+    gfsh.executeAndAssertThat(command,
+        "alter async-event-queue --id=test --batch-size=100 --if-exists").statusIsSuccess()
+        .containsOutput("Skipping: Can not find an async event queue with id");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  @Test
+  public void queueIdNotFoundInTheMap() throws Exception {
+    Configuration configuration = new Configuration("group");
+    configuration.setCacheXmlContent(getCacheXml("queue1", "queue2"));
+    configRegion.put("group", configuration);
+
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --batch-size=100 --id=queue")
+        .statusIsError().containsOutput("Can not find an async event queue");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  @Test
+  public void cannotLockClusterConfiguration() throws Exception {
+    when(service.lockSharedConfiguration()).thenReturn(false);
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --batch-size=100 --id=queue")
+        .statusIsError().containsOutput("Unable to lock the cluster configuration");
+  }
+
+  @Test
+  public void queueIdFoundInTheMap_updateBatchSize() throws Exception {
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --batch-size=100 --id=queue1")
+        .statusIsSuccess().tableHasRowCount("Group", 1)
+        .tableHasRowWithValues("Group", "Status", "group1", "Cluster Configuration Updated")
+        .containsOutput("Please restart the servers");
+
+    // verify that the xml is updated
+    Element element =
+        findAsyncEventQueueElement(configRegion.get("group1").getCacheXmlContent(), 0);
+    assertThat(element.getAttribute(ID)).isEqualTo("queue1");
+    assertThat(element.getAttribute(BATCH_SIZE)).isEqualTo("100");
+    assertThat(element.getAttribute(BATCH_TIME_INTERVAL)).isEqualTo("");
+    assertThat(element.getAttribute(MAX_QUEUE_MEMORY)).isEqualTo("");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  @Test
+  public void queueIdFoundInTheMap_updateBatchTimeInterval() throws Exception {
+    gfsh.executeAndAssertThat(command,
+        "alter async-event-queue --batch-time-interval=100 --id=queue1").statusIsSuccess()
+        .tableHasRowCount("Group", 1)
+        .tableHasRowWithValues("Group", "Status", "group1", "Cluster Configuration Updated")
+        .containsOutput("Please restart the servers");
+
+    // verify that the xml is updated
+    Element element =
+        findAsyncEventQueueElement(configRegion.get("group1").getCacheXmlContent(), 0);
+    assertThat(element.getAttribute(ID)).isEqualTo("queue1");
+    assertThat(element.getAttribute(BATCH_SIZE)).isEqualTo("");
+    assertThat(element.getAttribute(BATCH_TIME_INTERVAL)).isEqualTo("100");
+    assertThat(element.getAttribute(MAX_QUEUE_MEMORY)).isEqualTo("");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  @Test
+  public void queueIdFoundInTheMap_updateMaxMemory() throws Exception {
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --max-queue-memory=100 --id=queue1")
+        .statusIsSuccess().tableHasRowCount("Group", 1)
+        .tableHasRowWithValues("Group", "Status", "group1", "Cluster Configuration Updated")
+        .containsOutput("Please restart the servers");
+
+    // verify that the xml is updated
+    Element element =
+        findAsyncEventQueueElement(configRegion.get("group1").getCacheXmlContent(), 0);
+    assertThat(element.getAttribute(ID)).isEqualTo("queue1");
+    assertThat(element.getAttribute(BATCH_SIZE)).isEqualTo("");
+    assertThat(element.getAttribute(BATCH_TIME_INTERVAL)).isEqualTo("");
+    assertThat(element.getAttribute(MAXIMUM_QUEUE_MEMORY)).isEqualTo("100");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  @Test
+  public void multipleQueuesInClusterConfig() throws Exception {
+    when(configRegion.keySet()).thenReturn(Collections.singleton("group"));
+    Configuration configuration = new Configuration("group");
+    configuration.setCacheXmlContent(getCacheXml("queue1", "queue2"));
+    when(configRegion.get("group")).thenReturn(configuration);
+
+    gfsh.executeAndAssertThat(command, "alter async-event-queue --batch-size=100 --id=queue1")
+        .statusIsSuccess().tableHasRowCount("Group", 1)
+        .tableHasRowWithValues("Group", "Status", "group", "Cluster Configuration Updated")
+        .containsOutput("Please restart the servers");
+
+    // verify that queue1's xml is updated
+    Element element = findAsyncEventQueueElement(configRegion.get("group").getCacheXmlContent(),
0);
+    assertThat(element.getAttribute(ID)).isEqualTo("queue1");
+    assertThat(element.getAttribute(BATCH_SIZE)).isEqualTo("100");
+    assertThat(element.getAttribute(BATCH_TIME_INTERVAL)).isEqualTo("");
+    assertThat(element.getAttribute(MAX_QUEUE_MEMORY)).isEqualTo("");
+
+    // verify that queue2's xml is untouched
+    element = findAsyncEventQueueElement(configRegion.get("group").getCacheXmlContent(),
1);
+    assertThat(element.getAttribute(ID)).isEqualTo("queue2");
+    assertThat(element.getAttribute(BATCH_SIZE)).isEqualTo("");
+    assertThat(element.getAttribute(BATCH_TIME_INTERVAL)).isEqualTo("");
+    assertThat(element.getAttribute(MAX_QUEUE_MEMORY)).isEqualTo("");
+
+    verify(service).lockSharedConfiguration();
+    verify(service).unlockSharedConfiguration();
+  }
+
+  private Element findAsyncEventQueueElement(String xml, int index) throws Exception {
+    Document document = XmlUtils.createDocumentFromXml(xml);
+    NodeList nodeList = document.getElementsByTagName("async-event-queue");
+    return (Element) nodeList.item(index);
+  }
+
+  private String getAsyncEventQueueXml(String queueId) {
+    String xml = "<async-event-queue dispatcher-threads=\"1\" id=\"" + queueId + "\">\n"
+        + "    <async-event-listener>\n"
+        + "      <class-name>org.apache.geode.internal.cache.wan.MyAsyncEventListener</class-name>\n"
+        + "    </async-event-listener>\n" + "  </async-event-queue>\n";
+    return xml;
+  }
+
+  private String getCacheXml(String... queueIds) {
+    String xml = "<cache>\n" + Arrays.stream(queueIds).map(x -> getAsyncEventQueueXml(x))
+        .collect(Collectors.joining("\n")) + "</cache>";
+    return xml;
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/TabularResultDataTest.java
b/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/TabularResultDataTest.java
new file mode 100644
index 0000000..f812952
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/cli/result/TabularResultDataTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information
regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version
2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain
a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under
the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express
+ * or implied. See the License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+package org.apache.geode.management.internal.cli.result;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.UnitTest;
+
+
+@Category(UnitTest.class)
+public class TabularResultDataTest {
+
+  TabularResultData data;
+
+  @Before
+  public void before() throws Exception {
+    data = new TabularResultData();
+  }
+
+  @Test
+  public void rowColumnSize() throws Exception {
+    data.accumulate("key", "value1");
+    assertThat(data.rowSize("key")).isEqualTo(1);
+    assertThat(data.columnSize()).isEqualTo(1);
+
+    data.accumulate("key", "value2");
+    assertThat(data.rowSize("key")).isEqualTo(2);
+    assertThat(data.columnSize()).isEqualTo(1);
+
+    data.accumulate("key1", "value1");
+    assertThat(data.rowSize("key1")).isEqualTo(1);
+    assertThat(data.columnSize()).isEqualTo(2);
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfig.java
b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfig.java
index 57c0587..2a6f962 100644
--- a/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfig.java
+++ b/geode-core/src/test/java/org/apache/geode/management/internal/configuration/ClusterConfig.java
@@ -97,7 +97,7 @@ public class ClusterConfig implements Serializable {
       ClusterConfigurationService sc = internalLocator.getSharedConfiguration();
 
       // verify no extra configs exist in memory
-      Set<String> actualGroupConfigs = sc.getEntireConfiguration().keySet();
+      Set<String> actualGroupConfigs = sc.getConfigurationRegion().keySet();
       assertThat(actualGroupConfigs).isEqualTo(expectedGroupConfigs);
 
       for (ConfigGroup configGroup : this.getGroups()) {

-- 
To stop receiving notification emails like this one, please contact
['"commits@geode.apache.org" <commits@geode.apache.org>'].

Mime
View raw message