You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2018/03/26 17:37:38 UTC

[geode] 13/19: GEODE-1279: Rename Bug41733DUnitTest as BucketCreationRequesterCrashHARegressionTest

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

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

commit d93f3d554ed4d0746fedc90b220dd8a701c08f47
Author: Kirk Lund <kl...@apache.org>
AuthorDate: Thu Mar 22 19:48:11 2018 -0700

    GEODE-1279: Rename Bug41733DUnitTest as BucketCreationRequesterCrashHARegressionTest
---
 ...cketCreationRequesterCrashHARegressionTest.java | 261 +++++++++++++++++++++
 .../geode/internal/cache/Bug41733DUnitTest.java    | 211 -----------------
 2 files changed, 261 insertions(+), 211 deletions(-)

diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/BucketCreationRequesterCrashHARegressionTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/BucketCreationRequesterCrashHARegressionTest.java
new file mode 100644
index 0000000..c0e124f
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/BucketCreationRequesterCrashHARegressionTest.java
@@ -0,0 +1,261 @@
+/*
+ * 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.internal.cache;
+
+import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_CLUSTER_CONFIGURATION;
+import static org.apache.geode.distributed.ConfigurationProperties.ENABLE_NETWORK_PARTITION_DETECTION;
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.distributed.ConfigurationProperties.USE_CLUSTER_CONFIGURATION;
+import static org.apache.geode.test.dunit.DistributedTestUtils.crashDistributedSystem;
+import static org.apache.geode.test.dunit.Host.getHost;
+import static org.apache.geode.test.dunit.IgnoredException.addIgnoredException;
+import static org.apache.geode.test.dunit.Invoke.invokeInEveryVM;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.ForcedDisconnectException;
+import org.apache.geode.cache.AttributesFactory;
+import org.apache.geode.cache.DataPolicy;
+import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.distributed.DistributedSystemDisconnectedException;
+import org.apache.geode.distributed.Locator;
+import org.apache.geode.distributed.internal.ClusterDistributionManager;
+import org.apache.geode.distributed.internal.DistributionMessage;
+import org.apache.geode.distributed.internal.DistributionMessageObserver;
+import org.apache.geode.internal.cache.partitioned.ManageBucketMessage;
+import org.apache.geode.internal.cache.partitioned.ManageBucketMessage.ManageBucketReplyMessage;
+import org.apache.geode.test.dunit.NetworkUtils;
+import org.apache.geode.test.dunit.RMIException;
+import org.apache.geode.test.dunit.SerializableRunnableIF;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.cache.CacheTestCase;
+import org.apache.geode.test.dunit.rules.SharedErrorCollector;
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;
+import org.apache.geode.test.junit.rules.serializable.SerializableTestName;
+
+/**
+ * Test to make sure that we can handle a crash of the member directing bucket creation.
+ *
+ * BucketCreationRequesterCrashHARegressionTest
+ *
+ * <p>
+ * TRAC #41733: Hang in BucketAdvisor.waitForPrimaryMember
+ */
+@Category(DistributedTest.class)
+public class BucketCreationRequesterCrashHARegressionTest extends CacheTestCase {
+
+  private String uniqueName;
+  private String hostName;
+  private int locatorPort;
+  private File locatorLog;
+
+  private VM server1;
+  private VM server2;
+  private VM locator;
+
+  @Rule
+  public SerializableTemporaryFolder temporaryFolder = new SerializableTemporaryFolder();
+
+  @Rule
+  public SerializableTestName testName = new SerializableTestName();
+
+  @Rule
+  public SharedErrorCollector errorCollector = new SharedErrorCollector();
+
+  @Before
+  public void setUp() throws Exception {
+    server1 = getHost(0).getVM(0);
+    server2 = getHost(0).getVM(1);
+    locator = getHost(0).getVM(2);
+
+    uniqueName = getClass().getSimpleName() + "_" + testName.getMethodName();
+    hostName = NetworkUtils.getServerHostName(server1.getHost());
+    locatorLog = new File(temporaryFolder.newFolder(uniqueName), "locator.log");
+
+    locatorPort = locator.invoke(() -> startLocator());
+    assertThat(locatorPort).isGreaterThan(0);
+
+    server1.invoke(() -> createServerCache());
+    server2.invoke(() -> createServerCache());
+
+    // cluster should ONLY have 3 members (our 2 servers and 1 locator)
+    assertThat(server1.invoke(
+        () -> getCache().getDistributionManager().getDistributionManagerIdsIncludingAdmin()))
+            .hasSize(3);
+
+    addIgnoredException(ForcedDisconnectException.class);
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    DistributionMessageObserver.setInstance(null);
+    invokeInEveryVM(() -> {
+      DistributionMessageObserver.setInstance(null);
+    });
+
+    disconnectAllFromDS();
+  }
+
+  /**
+   * Test the we can handle a member departing after creating a bucket on the remote node but before
+   * we choose a primary
+   */
+  @Test
+  public void putShouldNotHangAfterBucketCrashesBeforePrimarySelection() throws Exception {
+    server1.invoke(
+        () -> handleBeforeProcessMessage(ManageBucketReplyMessage.class, () -> crashServer()));
+    server1.invoke(() -> createPartitionedRegion());
+
+    // Create a couple of buckets in VM0. This will make sure
+    // the next bucket we create will be created in VM 1.
+    server1.invoke(() -> putData(0, 2, "a"));
+
+    server2.invoke(() -> createPartitionedRegion());
+
+    // Trigger a bucket creation in VM1, which should cause server1 to close it's cache.
+    assertThatThrownBy(() -> server1.invoke(() -> putData(3, 4, "a")))
+        .isInstanceOf(RMIException.class)
+        .hasCauseInstanceOf(DistributedSystemDisconnectedException.class);
+
+    assertThat(server2.invoke(() -> getBucketList())).containsExactly(3);
+
+    // This shouldn't hang, because the bucket creation should finish,.
+    server2.invoke(() -> putData(3, 4, "a"));
+  }
+
+  /**
+   * Test the we can handle a member departing while we are in the process of creating the bucket on
+   * the remote node.
+   */
+  @Test
+  public void putShouldNotHangAfterServerWithBucketCrashes() throws Exception {
+    server2.invoke(() -> handleBeforeProcessMessage(ManageBucketMessage.class,
+        () -> server1.invoke(() -> crashServer())));
+    server1.invoke(() -> createPartitionedRegion());
+
+    // Create a couple of buckets in VM0. This will make sure
+    // the next bucket we create will be created in VM 1.
+    server1.invoke(() -> putData(0, 2, "a"));
+
+    server2.invoke(() -> createPartitionedRegion());
+
+    // Trigger a bucket creation in VM1, which should cause server1 to close it's cache.
+    assertThatThrownBy(() -> server1.invoke(() -> putData(3, 4, "a")))
+        .isInstanceOf(RMIException.class)
+        .hasCauseInstanceOf(DistributedSystemDisconnectedException.class);
+
+    assertThat(server2.invoke(() -> getBucketList())).containsExactly(3);
+
+    // This shouldn't hang, because the bucket creation should finish.
+    server2.invoke(() -> putData(3, 4, "a"));
+  }
+
+  private Properties createLocatorConfig() {
+    Properties config = new Properties();
+    config.setProperty(ENABLE_CLUSTER_CONFIGURATION, "false");
+    config.setProperty(ENABLE_NETWORK_PARTITION_DETECTION, "false");
+    config.setProperty(USE_CLUSTER_CONFIGURATION, "false");
+    return config;
+  }
+
+  private Properties createServerConfig() {
+    Properties config = createLocatorConfig();
+    config.setProperty(LOCATORS, hostName + "[" + locatorPort + "]");
+    return config;
+  }
+
+  private int startLocator() throws IOException {
+    Properties config = createLocatorConfig();
+    InetAddress bindAddress = InetAddress.getByName(hostName);
+    Locator locator = Locator.startLocatorAndDS(locatorPort, locatorLog, bindAddress, config);
+    return locator.getPort();
+  }
+
+  private void createServerCache() {
+    getCache(createServerConfig());
+  }
+
+  private void createPartitionedRegion() {
+    PartitionAttributesFactory paf = new PartitionAttributesFactory();
+    paf.setRedundantCopies(0);
+
+    AttributesFactory af = new AttributesFactory();
+    af.setDataPolicy(DataPolicy.PARTITION);
+    af.setPartitionAttributes(paf.create());
+
+    getCache().createRegion(uniqueName, af.create());
+  }
+
+  private void putData(final int startKey, final int endKey, final String value) {
+    Region<Integer, String> region = getCache().getRegion(uniqueName);
+
+    for (int i = startKey; i < endKey; i++) {
+      region.put(i, value);
+    }
+  }
+
+  private Set<Integer> getBucketList() {
+    PartitionedRegion region = (PartitionedRegion) getCache().getRegion(uniqueName);
+    return new TreeSet<>(region.getDataStore().getAllLocalBucketIds());
+  }
+
+  private void handleBeforeProcessMessage(final Class<? extends DistributionMessage> messageClass,
+      final SerializableRunnableIF runnable) {
+    DistributionMessageObserver
+        .setInstance(new RunnableBeforeProcessMessageObserver(messageClass, runnable));
+  }
+
+  private void crashServer() {
+    crashDistributedSystem(getSystem());
+  }
+
+  private class RunnableBeforeProcessMessageObserver extends DistributionMessageObserver {
+
+    private final Class<? extends DistributionMessage> messageClass;
+    private final SerializableRunnableIF runnable;
+
+    RunnableBeforeProcessMessageObserver(final Class<? extends DistributionMessage> messageClass,
+        final SerializableRunnableIF runnable) {
+      this.messageClass = messageClass;
+      this.runnable = runnable;
+    }
+
+    @Override
+    public void beforeProcessMessage(ClusterDistributionManager dm, DistributionMessage message) {
+      if (messageClass.isInstance(message)) {
+        try {
+          runnable.run();
+        } catch (Exception e) {
+          errorCollector.addError(e);
+        }
+      }
+    }
+  }
+}
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/Bug41733DUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/Bug41733DUnitTest.java
deleted file mode 100644
index ae2e664..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/cache/Bug41733DUnitTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.internal.cache;
-
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import org.apache.geode.cache.AttributesFactory;
-import org.apache.geode.cache.Cache;
-import org.apache.geode.cache.DataPolicy;
-import org.apache.geode.cache.PartitionAttributesFactory;
-import org.apache.geode.cache.Region;
-import org.apache.geode.distributed.*;
-import org.apache.geode.distributed.internal.ClusterDistributionManager;
-import org.apache.geode.distributed.internal.DistributionMessage;
-import org.apache.geode.distributed.internal.DistributionMessageObserver;
-import org.apache.geode.internal.cache.partitioned.ManageBucketMessage;
-import org.apache.geode.internal.cache.partitioned.ManageBucketMessage.ManageBucketReplyMessage;
-import org.apache.geode.test.dunit.Host;
-import org.apache.geode.test.dunit.RMIException;
-import org.apache.geode.test.dunit.SerializableCallable;
-import org.apache.geode.test.dunit.SerializableRunnable;
-import org.apache.geode.test.dunit.VM;
-import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
-import org.apache.geode.test.junit.categories.DistributedTest;
-
-/**
- * Test to make sure that we can handle a crash of the member directing bucket creation.
- */
-@Category(DistributedTest.class)
-public class Bug41733DUnitTest extends JUnit4CacheTestCase {
-
-  @Override
-  public final void preTearDownCacheTestCase() throws Exception {
-    disconnectAllFromDS();
-  }
-
-  @Override
-  public Properties getDistributedSystemProperties() {
-    Properties result = super.getDistributedSystemProperties();
-    result.put(ConfigurationProperties.ENABLE_NETWORK_PARTITION_DETECTION, "false");
-    return result;
-  }
-
-  /**
-   * Test the we can handle a member departing after creating a bucket on the remote node but before
-   * we choose a primary
-   */
-  @Test
-  public void testCrashAfterBucketCreation() throws Throwable {
-    Host host = Host.getHost(0);
-    VM vm0 = host.getVM(0);
-    VM vm1 = host.getVM(1);
-
-    vm0.invoke(new SerializableRunnable("Install observer") {
-
-      public void run() {
-        DistributionMessageObserver.setInstance(new DistributionMessageObserver() {
-
-
-          @Override
-          public void beforeProcessMessage(ClusterDistributionManager dm,
-              DistributionMessage message) {
-            if (message instanceof ManageBucketReplyMessage) {
-              disconnectFromDS();
-            }
-          }
-        });
-
-      }
-    });
-    createPR(vm0, 0);
-
-    // Create a couple of buckets in VM0. This will make sure
-    // the next bucket we create will be created in VM 1.
-    putData(vm0, 0, 2, "a");
-
-    createPR(vm1, 0);
-
-    // Trigger a bucket creation in VM1, which should cause vm0 to close it's cache.
-    try {
-      putData(vm0, 3, 4, "a");
-      fail("should have received a cache closed exception");
-    } catch (RMIException e) {
-      if (!(e.getCause() instanceof DistributedSystemDisconnectedException)) {
-        throw e;
-      }
-    }
-
-    assertEquals(Collections.singleton(3), getBucketList(vm1));
-
-    // This shouldn't hang, because the bucket creation should finish,.
-    putData(vm1, 3, 4, "a");
-  }
-
-  /**
-   * Test the we can handle a member departing while we are in the process of creating the bucket on
-   * the remote node.
-   */
-  @Test
-  public void testCrashDuringBucketCreation() throws Throwable {
-    Host host = Host.getHost(0);
-    final VM vm0 = host.getVM(0);
-    VM vm1 = host.getVM(1);
-
-    vm1.invoke(new SerializableRunnable("Install observer") {
-
-      public void run() {
-
-        DistributionMessageObserver.setInstance(new DistributionMessageObserver() {
-
-          @Override
-          public void beforeProcessMessage(ClusterDistributionManager dm,
-              DistributionMessage message) {
-            if (message instanceof ManageBucketMessage) {
-              vm0.invoke(() -> disconnectFromDS());
-            }
-          }
-        });
-
-      }
-    });
-    createPR(vm0, 0);
-
-    // Create a couple of buckets in VM0. This will make sure
-    // the next bucket we create will be created in VM 1.
-    putData(vm0, 0, 2, "a");
-
-    createPR(vm1, 0);
-
-    // Trigger a bucket creation in VM1, which should cause vm0 to close it's cache.
-    try {
-      putData(vm0, 3, 4, "a");
-      fail("should have received a cache closed exception");
-    } catch (RMIException e) {
-      if (!(e.getCause() instanceof DistributedSystemDisconnectedException)) {
-        throw e;
-      }
-    }
-
-    assertEquals(Collections.singleton(3), getBucketList(vm1));
-
-    // This shouldn't hang, because the bucket creation should finish,.
-    putData(vm1, 3, 4, "a");
-  }
-
-  private void createPR(VM vm0, final int redundancy) {
-    vm0.invoke(new SerializableRunnable("Create PR") {
-
-      public void run() {
-        Cache cache = getCache();
-        AttributesFactory af = new AttributesFactory();
-        PartitionAttributesFactory paf = new PartitionAttributesFactory();
-        paf.setRedundantCopies(redundancy);
-        af.setPartitionAttributes(paf.create());
-        af.setDataPolicy(DataPolicy.PARTITION);
-        cache.createRegion("region", af.create());
-      }
-
-    });
-  }
-
-  protected void putData(VM vm, final int startKey, final int endKey, final String value) {
-    SerializableRunnable createData = new SerializableRunnable() {
-
-      public void run() {
-        Cache cache = getCache();
-        Region region = cache.getRegion("region");
-
-        for (int i = startKey; i < endKey; i++) {
-          region.put(i, value);
-        }
-      }
-    };
-    vm.invoke(createData);
-  }
-
-  protected Set<Integer> getBucketList(VM vm0) {
-    return getBucketList(vm0, "region");
-  }
-
-  protected Set<Integer> getBucketList(VM vm0, final String regionName) {
-    SerializableCallable getBuckets = new SerializableCallable("get buckets") {
-
-      public Object call() throws Exception {
-        Cache cache = getCache();
-        PartitionedRegion region = (PartitionedRegion) cache.getRegion(regionName);
-        return new TreeSet<Integer>(region.getDataStore().getAllLocalBucketIds());
-      }
-    };
-
-    return (Set<Integer>) vm0.invoke(getBuckets);
-  }
-
-}

-- 
To stop receiving notification emails like this one, please contact
klund@apache.org.