You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by je...@apache.org on 2016/03/30 15:19:54 UTC

incubator-geode git commit: GEODE-1134: Some scenarios loading cluster config from dir do not work.

Repository: incubator-geode
Updated Branches:
  refs/heads/develop 78bc55d86 -> ffd920735


GEODE-1134: Some scenarios loading cluster config from dir do not work.


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/ffd92073
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/ffd92073
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/ffd92073

Branch: refs/heads/develop
Commit: ffd9207350d612d0c88e27fad45c9b5494203c68
Parents: 78bc55d
Author: Jens Deppe <jd...@pivotal.io>
Authored: Mon Mar 28 07:33:36 2016 -0700
Committer: Jens Deppe <jd...@pivotal.io>
Committed: Wed Mar 30 06:19:15 2016 -0700

----------------------------------------------------------------------
 .../internal/SharedConfiguration.java           |  17 +-
 .../SharedConfigurationUsingDirDUnitTest.java   | 322 +++++++++++++++++++
 .../internal/configuration/cluster-empty.xml    |  30 ++
 .../internal/configuration/cluster-region.xml   |  33 ++
 4 files changed, 394 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ffd92073/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/SharedConfiguration.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/SharedConfiguration.java b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/SharedConfiguration.java
index 38dd5da..a8f331a 100644
--- a/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/SharedConfiguration.java
+++ b/geode-core/src/main/java/com/gemstone/gemfire/distributed/internal/SharedConfiguration.java
@@ -49,7 +49,6 @@ import org.w3c.dom.Document;
 import org.xml.sax.SAXException;
 
 import com.gemstone.gemfire.CancelException;
-import com.gemstone.gemfire.LogWriter;
 import com.gemstone.gemfire.cache.AttributesFactory;
 import com.gemstone.gemfire.cache.Cache;
 import com.gemstone.gemfire.cache.DataPolicy;
@@ -311,16 +310,18 @@ public class SharedConfiguration {
               File zipFile = new File(zipFileName);
               byte[] zipBytes = FileUtils.readFileToByteArray(zipFile);
               Object [] args = new Object[] {zipFileName, zipBytes};
-              CliUtil.executeFunction(fn, args, locatorsWithSC);
+              // Make sure we wait for the result. The fn also does a clear on the config
+              // region so there is a race with the clear below.
+              CliUtil.executeFunction(fn, args, locatorsWithSC).getResult();
             } catch (Exception e) {
               logger.error(e.getMessage(), e);
             }
           }
-          //Clear the configuration region and load the configuration read from the 'shared_config' directory
-          configRegion.clear();
-          configRegion.putAll(sharedConfigMap);
-        } 
-      }finally {
+        }
+        //Clear the configuration region and load the configuration read from the 'shared_config' directory
+        configRegion.clear();
+        configRegion.putAll(sharedConfigMap);
+      } finally {
         unlockSharedConfiguration();
       }
     } else {
@@ -372,9 +373,9 @@ public class SharedConfiguration {
       boolean isLocked = sharedConfigLockingService.lock(SHARED_CONFIG_LOCK_NAME, 5000, 5000);
       try {
         if (isLocked) {
-          logger.info("Building up configuration response with following configurations");
           Set<String> groups = configRequest.getGroups();
           groups.add(SharedConfiguration.CLUSTER_CONFIG);
+          logger.info("Building up configuration response with following configurations: {}", groups);
 
           for (String group : groups) {
             Configuration configuration = getConfiguration(group);

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ffd92073/geode-core/src/test/java/com/gemstone/gemfire/management/internal/configuration/SharedConfigurationUsingDirDUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/com/gemstone/gemfire/management/internal/configuration/SharedConfigurationUsingDirDUnitTest.java b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/configuration/SharedConfigurationUsingDirDUnitTest.java
new file mode 100644
index 0000000..b625cfa
--- /dev/null
+++ b/geode-core/src/test/java/com/gemstone/gemfire/management/internal/configuration/SharedConfigurationUsingDirDUnitTest.java
@@ -0,0 +1,322 @@
+/*
+ * 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 com.gemstone.gemfire.management.internal.configuration;
+
+import com.gemstone.gemfire.cache.Region;
+import com.gemstone.gemfire.distributed.Locator;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.distributed.internal.InternalLocator;
+import com.gemstone.gemfire.distributed.internal.SharedConfiguration;
+import com.gemstone.gemfire.internal.AvailablePortHelper;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.VM;
+import com.gemstone.gemfire.test.dunit.cache.internal.JUnit4CacheTestCase;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
+import com.gemstone.gemfire.util.test.TestUtil;
+import com.jayway.awaitility.Awaitility;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import static java.util.stream.Collectors.joining;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+@Category(DistributedTest.class)
+public class SharedConfigurationUsingDirDUnitTest extends JUnit4CacheTestCase {
+
+  @After
+  public void teardown() throws Exception {
+    for (int i = 0; i < 2; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      vm.invoke("Removing shared configuration", () -> {
+        InternalLocator locator = InternalLocator.getLocator();
+        if (locator == null) {
+          return;
+        }
+
+        SharedConfiguration sharedConfig = locator.getSharedConfiguration();
+        if (sharedConfig != null) {
+          sharedConfig.destroySharedConfiguration();
+        }
+      });
+    }
+  }
+
+  @Test
+  public void basicClusterConfigDirWithOneLocator() throws Exception {
+    final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(1);
+    final int locatorCount = ports.length;
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-region.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region presence", () -> {
+        Awaitility.waitAtMost(15, TimeUnit.SECONDS).until(() -> getRootRegion("newReplicatedRegion") != null);
+      });
+    }
+  }
+
+  @Test
+  public void basicClusterConfigDirWithTwoLocators() throws Exception {
+    final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
+    final int locatorCount = ports.length;
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-region.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region presence", () -> {
+        Awaitility.waitAtMost(15, TimeUnit.SECONDS).until(() -> getRootRegion("newReplicatedRegion") != null);
+      });
+    }
+  }
+
+  @Test
+  public void updateClusterConfigDirWithTwoLocatorsNoRollingServerRestart() throws Exception {
+    final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
+    final int locatorCount = ports.length;
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-empty.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region absence", () -> {
+        Region r = getRootRegion("newReplicatedRegion");
+        assertNull("Region does exist", r);
+      });
+    }
+
+    // Shut down the locators in reverse order to how we will start them up in the next step.
+    // Unless we start them asynchronously, the older one will want to wait for a new diskstore
+    // to become available and will time out.
+    for (int i = locatorCount; i > 0; i--) {
+      VM vm = Host.getHost(0).getVM(i - 1);
+      stopLocator(vm);
+    }
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-region.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      vm.invoke(() -> disconnectFromDS());
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region presence", () -> {
+        Awaitility.waitAtMost(15, TimeUnit.SECONDS).until(() -> getRootRegion("newReplicatedRegion") != null);
+      });
+    }
+  }
+
+  @Test
+  public void updateClusterConfigDirWithTwoLocatorsAndRollingServerRestart() throws Exception {
+    final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
+    final int locatorCount = ports.length;
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-empty.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region absence", () -> {
+        Region r = getRootRegion("newReplicatedRegion");
+        assertNull("Region does exist", r);
+      });
+    }
+
+    // Shut down the locators in reverse order to how we will start them up in the next step.
+    // Unless we start them asynchronously, the older one will want to wait for a new diskstore
+    // to become available and will time out.
+    for (int i = locatorCount; i > 0; i--) {
+      VM vm = Host.getHost(0).getVM(i - 1);
+      stopLocator(vm);
+    }
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-region.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region presence", () -> {
+        Awaitility.waitAtMost(15, TimeUnit.SECONDS).until(() -> getRootRegion("newReplicatedRegion") != null);
+      });
+    }
+  }
+
+  @Test
+  public void updateClusterConfigDirWithTwoLocatorsRollingRestartAndRollingServerRestart() throws Exception {
+    final int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
+    final int locatorCount = ports.length;
+
+    for (int i = 0; i < locatorCount; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      copyClusterXml(vm, "cluster-empty.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region absence", () -> {
+        Region r = getRootRegion("newReplicatedRegion");
+        assertNull("Region does exist", r);
+      });
+    }
+
+    // Roll the locators
+    for (int i = locatorCount - 1; i >= 0; i--) {
+      VM vm = Host.getHost(0).getVM(i);
+      stopLocator(vm);
+      copyClusterXml(vm, "cluster-region.xml");
+      startLocator(vm, i, ports);
+      waitForSharedConfiguration(vm);
+    }
+
+    // Roll the servers
+    for (int i = 2; i < 4; i++) {
+      VM vm = Host.getHost(0).getVM(i);
+      restartCache(vm, i, ports);
+
+      vm.invoke("Checking for region presence", () -> {
+        Awaitility.waitAtMost(15, TimeUnit.SECONDS).until(() -> getRootRegion("newReplicatedRegion") != null);
+      });
+    }
+  }
+
+  private void copyClusterXml(final VM vm, final String clusterXml) {
+    vm.invoke("Copying new cluster.xml from " + clusterXml, () -> {
+      String clusterXmlPath = TestUtil.getResourcePath(SharedConfigurationUsingDirDUnitTest.class, clusterXml);
+      InputStream cacheXml = new FileInputStream(clusterXmlPath);
+      assertNotNull("Could not create InputStream from " + clusterXmlPath, cacheXml);
+      Files.createDirectories(Paths.get("cluster_config", "cluster"));
+      Files.copy(cacheXml, Paths.get("cluster_config", "cluster", "cluster.xml"), StandardCopyOption.REPLACE_EXISTING);
+    });
+  }
+
+  private void startLocator(final VM vm, final int i, final int[] locatorPorts) {
+    vm.invoke("Creating locator on " + vm, () -> {
+      final String locatorName = "locator" + i;
+      final File logFile = new File("locator-" + i + ".log");
+      final Properties props = new Properties();
+      props.setProperty(DistributionConfig.NAME_NAME, locatorName);
+      props.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
+      props.setProperty(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "true");
+      props.setProperty(DistributionConfig.LOAD_CLUSTER_CONFIG_FROM_DIR_NAME, "true");
+
+      if (locatorPorts.length > 1) {
+        int otherLocatorPort = locatorPorts[(i + 1) % locatorPorts.length];
+        props.setProperty(DistributionConfig.LOCATORS_NAME, "localhost[" + otherLocatorPort + "]");
+      }
+
+      Locator.startLocatorAndDS(locatorPorts[i], logFile, props);
+    });
+  }
+
+  private void waitForSharedConfiguration(final VM vm) {
+    vm.invoke("Waiting for shared configuration", () -> {
+      final InternalLocator locator = InternalLocator.getLocator();
+      Awaitility.waitAtMost(15, TimeUnit.SECONDS).until(() -> {
+        return locator.isSharedConfigurationRunning();
+      });
+    });
+  }
+
+  private void stopLocator(final VM vm) {
+    vm.invoke("Stopping locator on " + vm, () -> {
+      InternalLocator locator = InternalLocator.getLocator();
+      assertNotNull("No locator found", locator);
+      locator.stop();
+      disconnectAllFromDS();
+    });
+  }
+
+  private void restartCache(final VM vm, final int i, final int[] locatorPorts) {
+    vm.invoke("Creating cache on VM " + i, () -> {
+      disconnectFromDS();
+
+      final Properties props = new Properties();
+      props.setProperty(DistributionConfig.NAME_NAME, "member" + i);
+      props.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
+      props.setProperty(DistributionConfig.LOCATORS_NAME, getLocatorStr(locatorPorts));
+      props.setProperty(DistributionConfig.LOG_FILE_NAME, "server-" + i + ".log");
+      props.setProperty(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, "true");
+      props.setProperty(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "true");
+
+      getSystem(props);
+      getCache();
+    });
+  }
+
+  private String getLocatorStr(final int[] locatorPorts) {
+    return Arrays.stream(locatorPorts).mapToObj(p -> "localhost[" + p + "]").collect(joining(","));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ffd92073/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-empty.xml
----------------------------------------------------------------------
diff --git a/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-empty.xml b/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-empty.xml
new file mode 100644
index 0000000..60882e1
--- /dev/null
+++ b/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-empty.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!--
+  Used by com/gemstone/gemfire/management/internal/configuration/SharedConfigurationUsingDirDUnitTest.java
+-->
+<cache xsi:schemaLocation="http://schema.pivotal.io/gemfire/cache http://schema.pivotal.io/gemfire/cache/cache-8.1.xsd"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://schema.pivotal.io/gemfire/cache"
+       version="8.1"
+       lock-lease="120"
+       lock-timeout="60"
+       search-timeout="300"
+       is-server="false"
+       copy-on-read="false">
+</cache>

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/ffd92073/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-region.xml
----------------------------------------------------------------------
diff --git a/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-region.xml b/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-region.xml
new file mode 100644
index 0000000..8e8281a
--- /dev/null
+++ b/geode-core/src/test/resources/com/gemstone/gemfire/management/internal/configuration/cluster-region.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+<!--
+  Used by com/gemstone/gemfire/management/internal/configuration/SharedConfigurationUsingDirDUnitTest.java
+-->
+<cache xsi:schemaLocation="http://schema.pivotal.io/gemfire/cache http://schema.pivotal.io/gemfire/cache/cache-8.1.xsd"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns="http://schema.pivotal.io/gemfire/cache"
+       version="8.1"
+       lock-lease="120"
+       lock-timeout="60"
+       search-timeout="300"
+       is-server="false"
+       copy-on-read="false">
+  <region name="newReplicatedRegion">
+    <region-attributes scope="distributed-ack" data-policy="replicate"/>
+  </region>
+</cache>