You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by up...@apache.org on 2019/03/21 20:58:48 UTC

[geode] branch develop updated: GEODE-6271: Ignore failures from other pools

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

upthewaterspout 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 ec5a24b  GEODE-6271: Ignore failures from other pools
ec5a24b is described below

commit ec5a24b78c51b6a29b8bf656f91004d09510d244
Author: Dan Smith <up...@apache.org>
AuthorDate: Thu Mar 21 10:59:30 2019 -0700

    GEODE-6271: Ignore failures from other pools
    
    Copying a type to additional pools on the client may fail if not servers
    are running in those additional pools. Ignoring failures due to copying
    a type from one pool to another.
---
 .../pdx/PdxMultiClusterClientServerDUnitTest.java  | 42 ++++++++++++
 .../geode/pdx/internal/ClientTypeRegistration.java | 74 ++++++++++++++--------
 2 files changed, 88 insertions(+), 28 deletions(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/pdx/PdxMultiClusterClientServerDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/pdx/PdxMultiClusterClientServerDUnitTest.java
index f0ce16e..b01ea46 100644
--- a/geode-core/src/distributedTest/java/org/apache/geode/pdx/PdxMultiClusterClientServerDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/pdx/PdxMultiClusterClientServerDUnitTest.java
@@ -50,10 +50,13 @@ public class PdxMultiClusterClientServerDUnitTest extends JUnit4CacheTestCase {
   public static final String REGION_NAME = "testSimplePdx";
   public static final int SITE_A_DSID = 1;
   public static final int SITE_B_DSID = 2;
+  public static final int SITE_C_DSID = 3;
   private VM locatorA;
   private VM locatorB;
+  private VM locatorC;
   private VM serverA;
   private VM serverB;
+  private VM serverC;
 
   @Before
   public void setupVMs() {
@@ -61,6 +64,8 @@ public class PdxMultiClusterClientServerDUnitTest extends JUnit4CacheTestCase {
     locatorB = VM.getVM(1);
     serverA = VM.getVM(2);
     serverB = VM.getVM(3);
+    locatorC = VM.getVM(4);
+    serverC = VM.getVM(5);
   }
 
   @Test
@@ -136,6 +141,43 @@ public class PdxMultiClusterClientServerDUnitTest extends JUnit4CacheTestCase {
         getCache().getRegion("regionA").get("key")));
   }
 
+  /**
+   * If a client has multiple pools, but one of the pools has no available servers, creating
+   * a new type should still succeed.
+   */
+  @Test
+  public void sendingTypeIgnoresClustersThatAreNotRunning() {
+
+    ClientCache client = createScenario();
+    int siteCLocatorPort = createLocator(locatorC, SITE_C_DSID);
+
+    createServerRegion(serverC, siteCLocatorPort, "regionC", SITE_C_DSID);
+
+    Pool poolC =
+        PoolManager.createFactory().addLocator("localhost", siteCLocatorPort).create("poolC");
+
+    client.createClientRegionFactory(ClientRegionShortcut.PROXY)
+        .setPoolName("poolC")
+        .create("regionC");
+
+    Region regionA = client.getRegion("regionA");
+    Region regionC = client.getRegion("regionC");
+
+    createType(serverA, "regionA");
+
+    serverB.invoke(JUnit4CacheTestCase::closeCache);
+
+    // Put from the client serverA. This will try to send the type to serverB and serverC
+    regionA.put("key", new SimpleClass(5, (byte) 6));
+    regionC.put("key", new SimpleClass(5, (byte) 6));
+
+    // Make sure both remaining servers can deserialize the type
+    serverC.invoke(() -> assertEquals(new SimpleClass(5, (byte) 6),
+        getCache().getRegion("regionC").get("key")));
+    serverA.invoke(() -> assertEquals(new SimpleClass(5, (byte) 6),
+        getCache().getRegion("regionA").get("key")));
+  }
+
   private void createType(VM vm, String region) {
     vm.invoke(() -> {
       getCache().getRegion(region).put("createType", new SimpleClass(5, (byte) 6));
diff --git a/geode-core/src/main/java/org/apache/geode/pdx/internal/ClientTypeRegistration.java b/geode-core/src/main/java/org/apache/geode/pdx/internal/ClientTypeRegistration.java
index 6f24d35..5cbe02c 100644
--- a/geode-core/src/main/java/org/apache/geode/pdx/internal/ClientTypeRegistration.java
+++ b/geode-core/src/main/java/org/apache/geode/pdx/internal/ClientTypeRegistration.java
@@ -68,7 +68,7 @@ public class ClientTypeRegistration implements TypeRegistration {
       try {
         newTypeId = GetPDXIdForTypeOp.execute((ExecutablePool) pool, newType);
         newType.setTypeId(newTypeId);
-        sendTypeToAllPools(newType, newTypeId, getAllPoolsExcept(pool));
+        copyTypeToOtherPools(newType, newTypeId, pool);
         return newTypeId;
       } catch (ServerConnectivityException e) {
         // ignore, try the next pool.
@@ -78,6 +78,22 @@ public class ClientTypeRegistration implements TypeRegistration {
     throw returnCorrectExceptionForFailure(pools, newTypeId, lastException);
   }
 
+  /**
+   * Send a type to all pools. This used to make sure that any types
+   * used by this client make it to all clusters this client is connected to.
+   */
+  private void copyTypeToOtherPools(PdxType newType, int newTypeId, Pool exception) {
+    Collection<Pool> pools = getAllPoolsExcept(exception);
+    for (Pool pool : pools) {
+      try {
+        sendTypeToPool(newType, newTypeId, pool);
+      } catch (ServerConnectivityException e) {
+        logger.debug("Received an exception sending pdx type to pool {}, {}", pool, e.getMessage(),
+            e);
+      }
+    }
+  }
+
   private Collection<Pool> getAllPoolsExcept(Pool pool) {
     Collection<Pool> targetPools = new ArrayList<>(getAllPools());
     targetPools.remove(pool);
@@ -181,8 +197,7 @@ public class ClientTypeRegistration implements TypeRegistration {
     for (Pool pool : pools) {
       try {
         int result = GetPDXIdForEnumOp.execute((ExecutablePool) pool, enumInfo);
-
-        sendEnumToAllPools(enumInfo, result, getAllPoolsExcept(pool));
+        copyEnumToOtherPools(enumInfo, result, pool);
         return result;
       } catch (ServerConnectivityException e) {
         // ignore, try the next pool.
@@ -192,6 +207,21 @@ public class ClientTypeRegistration implements TypeRegistration {
     throw returnCorrectExceptionForFailure(pools, -1, lastException);
   }
 
+  /**
+   * Send an enum to all pools. This used to make sure that any enums
+   * used by this client make it to all clusters this client is connected to.
+   */
+  private void copyEnumToOtherPools(EnumInfo enumInfo, int newTypeId, Pool exception) {
+    Collection<Pool> pools = getAllPoolsExcept(exception);
+    for (Pool pool : pools) {
+      try {
+        sendEnumIdToPool(enumInfo, newTypeId, pool);
+      } catch (ServerConnectivityException e) {
+        logger.debug("Received an exception sending pdx enum to pool {}, {}", pool, e.getMessage());
+      }
+    }
+  }
+
   private void sendEnumIdToPool(EnumInfo enumInfo, int id, Pool pool) {
     try {
       AddPDXEnumOp.execute((ExecutablePool) pool, id, enumInfo);
@@ -295,51 +325,39 @@ public class ClientTypeRegistration implements TypeRegistration {
     return true;
   }
 
+  /**
+   * Add an type as part of an import. The type is sent to all pools in case
+   * the pools are connected to different clusters, but if one pool fails
+   * the import will fail.
+   */
   @Override
   public void addImportedType(int typeId, PdxType importedType) {
-    sendTypeToAllPools(importedType, typeId, getAllPools());
-  }
-
-  private void sendTypeToAllPools(PdxType importedType, int typeId,
-      Collection<Pool> pools) {
-    ServerConnectivityException lastException = null;
+    Collection<Pool> pools = getAllPools();
     for (Pool pool : pools) {
       try {
         sendTypeToPool(importedType, typeId, pool);
       } catch (ServerConnectivityException e) {
-        lastException = e;
-        break;
+        throw returnCorrectExceptionForFailure(pools, typeId, e);
       }
     }
-    if (lastException == null) {
-      return;
-    }
-    throw returnCorrectExceptionForFailure(pools, typeId, lastException);
   }
 
+  /**
+   * Add an enum as part of an import. The enum is sent to all pools in case
+   * the pools are connected to different clusters, but if one pool fails
+   * the import will fail.
+   */
   @Override
   public void addImportedEnum(int enumId, EnumInfo importedInfo) {
     Collection<Pool> pools = getAllPools();
 
-    sendEnumToAllPools(importedInfo, enumId, pools);
-    return;
-  }
-
-  private void sendEnumToAllPools(EnumInfo importedInfo, int enumId, Collection<Pool> pools) {
-    ServerConnectivityException lastException = null;
     for (Pool pool : pools) {
       try {
         sendEnumIdToPool(importedInfo, enumId, pool);
       } catch (ServerConnectivityException e) {
-        lastException = e;
-        break;
+        throw returnCorrectExceptionForFailure(pools, enumId, e);
       }
     }
-    if (lastException == null) {
-      return;
-    }
-
-    throw returnCorrectExceptionForFailure(pools, enumId, lastException);
   }
 
   private RuntimeException returnCorrectExceptionForFailure(final Collection<Pool> pools,