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/19 23:58:46 UTC
[geode] branch develop updated: GEODE-6271: Restoring pdx type
copying behavior in client
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 428b55b GEODE-6271: Restoring pdx type copying behavior in client
428b55b is described below
commit 428b55b200fa520529f9ed4dc81e5befdba85c84
Author: Dan Smith <ds...@pivotal.io>
AuthorDate: Tue Mar 19 16:58:27 2019 -0700
GEODE-6271: Restoring pdx type copying behavior in client
Some users were relying on having PDX types copied from one cluster to
another in the client. This logic was removed (accidentally?) in
cf0b378429. Restoring the original behavior to copy a type from one
cluster to another when it is created.
Note that receiving a type through a read still does not result in
copying a type from one cluster to another, so this topology is not
completely supported even with this fix.
---
.../pdx/PdxMultiClusterClientServerDUnitTest.java | 204 +++++++++++++++++++++
.../geode/pdx/internal/ClientTypeRegistration.java | 22 ++-
2 files changed, 223 insertions(+), 3 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
new file mode 100644
index 0000000..f0ce16e
--- /dev/null
+++ b/geode-core/src/distributedTest/java/org/apache/geode/pdx/PdxMultiClusterClientServerDUnitTest.java
@@ -0,0 +1,204 @@
+/*
+ * 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.pdx;
+
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.client.Pool;
+import org.apache.geode.cache.client.PoolManager;
+import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.distributed.ConfigurationProperties;
+import org.apache.geode.distributed.Locator;
+import org.apache.geode.test.dunit.SerializableCallableIF;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
+import org.apache.geode.test.junit.categories.SerializationTest;
+
+/**
+ * Test of how PDX works when a single client is connected to multiple
+ * clusters (that are not connected to each other through WAN).
+ */
+@Category({SerializationTest.class})
+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;
+ private VM locatorA;
+ private VM locatorB;
+ private VM serverA;
+ private VM serverB;
+
+ @Before
+ public void setupVMs() {
+ locatorA = VM.getVM(0);
+ locatorB = VM.getVM(1);
+ serverA = VM.getVM(2);
+ serverB = VM.getVM(3);
+ }
+
+ @Test
+ public void putFromOneClientToTwoClustersSendsTypeToBothClusters() {
+
+ ClientCache client = createScenario();
+
+ Region regionA = client.getRegion("regionA");
+ Region regionB = client.getRegion("regionB");
+
+ regionA.put("key", new SimpleClass(5, (byte) 6));
+ regionB.put("key", new SimpleClass(5, (byte) 6));
+
+ serverB.invoke(() -> assertEquals(new SimpleClass(5, (byte) 6),
+ getCache().getRegion("regionB").get("key")));
+ serverA.invoke(() -> assertEquals(new SimpleClass(5, (byte) 6),
+ getCache().getRegion("regionA").get("key")));
+ }
+
+ /**
+ * Test that if a value is copied from one cluster to another using the client,
+ * the new cluster will be able to deserialize the value.
+ */
+ @Test
+ @Ignore("This use case is not currently supported")
+ public void copyingValueFromOneClusterToAnotherUsingClientCopiesType() {
+
+ ClientCache client = createScenario();
+
+ Region regionA = client.getRegion("regionA");
+ Region regionB = client.getRegion("regionB");
+
+ // Put into serverA ( which will create the pdx type in serverA)
+ serverA.invoke(() -> {
+ getCache().getRegion("regionA").put("key", new SimpleClass(5, (byte) 6));
+
+ });
+
+ // Copy the value from serverA to serverB
+ regionB.put("key", regionA.get("key"));
+
+ // Make sure serverB can deserialize the value
+ serverB.invoke(() -> assertEquals(new SimpleClass(5, (byte) 6),
+ getCache().getRegion("regionB").get("key")));
+ }
+
+ /**
+ * See what happens if both clusters have independently defined a type, and then
+ * a client does a put in both clusters.
+ *
+ * It will get the type from one of the clusters, so the question is if it can be deserialized
+ * in both
+ */
+ @Test
+ public void bothClustersDefineTypeAndClientPutsInBothClusters() {
+
+ ClientCache client = createScenario();
+
+ Region regionA = client.getRegion("regionA");
+ Region regionB = client.getRegion("regionB");
+
+ createType(serverA, "regionA");
+ createType(serverB, "regionB");
+
+ // Put from the client into both servers (this will fetch the type from one of them)
+ regionA.put("key", new SimpleClass(5, (byte) 6));
+ regionB.put("key", new SimpleClass(5, (byte) 6));
+
+ // Make sure both servers can deserialize the type
+ serverB.invoke(() -> assertEquals(new SimpleClass(5, (byte) 6),
+ getCache().getRegion("regionB").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));
+
+ });
+ }
+
+ /**
+ * Create the two sites (A and B) the client.
+ *
+ * The client has two regions
+ * - regionA = connected using poolA to serverA
+ * - regionB = connected using poolB to serverB
+ */
+ private ClientCache createScenario() {
+ int siteALocatorPort = createLocator(locatorA, SITE_A_DSID);
+ int siteBLocatorPort = createLocator(locatorB, SITE_B_DSID);
+
+ createServerRegion(serverA, siteALocatorPort, "regionA", SITE_A_DSID);
+ createServerRegion(serverB, siteBLocatorPort, "regionB", SITE_B_DSID);
+
+ ClientCache client = new ClientCacheFactory().create();
+
+ Pool poolA =
+ PoolManager.createFactory().addLocator("localhost", siteALocatorPort).create("poolA");
+ Pool poolB =
+ PoolManager.createFactory().addLocator("localhost", siteBLocatorPort).create("poolB");
+
+ client.createClientRegionFactory(ClientRegionShortcut.PROXY)
+ .setPoolName("poolA")
+ .create("regionA");
+
+ client.createClientRegionFactory(ClientRegionShortcut.PROXY)
+ .setPoolName("poolB")
+ .create("regionB");
+ return client;
+ }
+
+ private int createLocator(VM vm, int dsid) {
+ return vm.invoke(() -> {
+
+ Properties properties = new Properties();
+ properties.setProperty(ConfigurationProperties.DISTRIBUTED_SYSTEM_ID, Integer.toString(dsid));
+ Locator locator = Locator.startLocatorAndDS(0, null, null);
+ return locator.getPort();
+ });
+ }
+
+
+ private int createServerRegion(VM vm, int locatorPort, String regionName, int dsid) {
+ SerializableCallableIF<Integer> createRegion = () -> {
+ Properties properties = new Properties();
+ properties.setProperty(LOCATORS, "localhost[" + locatorPort + "]");
+ properties.setProperty(ConfigurationProperties.DISTRIBUTED_SYSTEM_ID, Integer.toString(dsid));
+ Cache cache = getCache(properties);
+ cache.createRegionFactory(RegionShortcut.REPLICATE).create(regionName);
+ CacheServer cacheServer = cache.addCacheServer();
+ cacheServer.setPort(0);
+ cacheServer.start();
+ return cacheServer.getPort();
+ };
+
+ return vm.invoke(createRegion);
+ }
+
+}
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 f4010da..6f24d35 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
@@ -14,6 +14,7 @@
*/
package org.apache.geode.pdx.internal;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -67,7 +68,7 @@ public class ClientTypeRegistration implements TypeRegistration {
try {
newTypeId = GetPDXIdForTypeOp.execute((ExecutablePool) pool, newType);
newType.setTypeId(newTypeId);
- sendTypeToPool(newType, newTypeId, pool);
+ sendTypeToAllPools(newType, newTypeId, getAllPoolsExcept(pool));
return newTypeId;
} catch (ServerConnectivityException e) {
// ignore, try the next pool.
@@ -77,6 +78,12 @@ public class ClientTypeRegistration implements TypeRegistration {
throw returnCorrectExceptionForFailure(pools, newTypeId, lastException);
}
+ private Collection<Pool> getAllPoolsExcept(Pool pool) {
+ Collection<Pool> targetPools = new ArrayList<>(getAllPools());
+ targetPools.remove(pool);
+ return targetPools;
+ }
+
private void sendTypeToPool(PdxType type, int id, Pool pool) {
try {
AddPDXTypeOp.execute((ExecutablePool) pool, id, type);
@@ -174,7 +181,8 @@ public class ClientTypeRegistration implements TypeRegistration {
for (Pool pool : pools) {
try {
int result = GetPDXIdForEnumOp.execute((ExecutablePool) pool, enumInfo);
- sendEnumIdToPool(enumInfo, result, pool);
+
+ sendEnumToAllPools(enumInfo, result, getAllPoolsExcept(pool));
return result;
} catch (ServerConnectivityException e) {
// ignore, try the next pool.
@@ -289,8 +297,11 @@ public class ClientTypeRegistration implements TypeRegistration {
@Override
public void addImportedType(int typeId, PdxType importedType) {
- Collection<Pool> pools = getAllPools();
+ sendTypeToAllPools(importedType, typeId, getAllPools());
+ }
+ private void sendTypeToAllPools(PdxType importedType, int typeId,
+ Collection<Pool> pools) {
ServerConnectivityException lastException = null;
for (Pool pool : pools) {
try {
@@ -310,6 +321,11 @@ public class ClientTypeRegistration implements TypeRegistration {
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 {