You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2018/01/31 18:28:01 UTC

[geode] branch develop updated: GEODE-4375: Fix problem that an exception occurs when transaction from CacheServer via Pool (#1363)

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

dschneider 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 c6ce067  GEODE-4375: Fix problem that an exception occurs when transaction from CacheServer via Pool (#1363)
c6ce067 is described below

commit c6ce06713142ede2beabb4f2aaef4b08dbb6fccf
Author: Masaki Yamakawa <ma...@ulsystems.co.jp>
AuthorDate: Thu Feb 1 03:27:57 2018 +0900

    GEODE-4375: Fix problem that an exception occurs when transaction from CacheServer via Pool (#1363)
---
 .../geode/internal/cache/TXCommitMessage.java      |  16 +-
 .../BugTxCommitMessageDesiralizeDUnitTest.java     | 619 +++++++++++++++++++++
 .../codeAnalysis/sanctionedDataSerializables.txt   |   2 +-
 3 files changed, 635 insertions(+), 2 deletions(-)

diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java b/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java
index 9b4cab2..15ad7f6 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/TXCommitMessage.java
@@ -1384,7 +1384,7 @@ public class TXCommitMessage extends PooledDistributionMessage
         for (int i = 0; i < size; i++) {
           FarSideEntryOp entryOp = new FarSideEntryOp();
           // shadowkey is not being sent to clients
-          entryOp.fromData(in, largeModCount, !this.msg.getDM().isLoner());
+          entryOp.fromData(in, largeModCount, hasShadowKey(regionPath, parentRegionPath));
           if (entryOp.versionTag != null && this.memberId != null) {
             entryOp.versionTag.setMemberID(this.memberId);
           }
@@ -1395,6 +1395,20 @@ public class TXCommitMessage extends PooledDistributionMessage
       }
     }
 
+    private boolean hasShadowKey(String regionPath, String parentRegionPath) {
+      // in bucket region, regionPath is bucket name, use parentRegionPath
+      String path = parentRegionPath != null ? parentRegionPath : regionPath;
+      LocalRegion region = getRegionByPath(msg.getDM(), path);
+
+      // default value is whether loner or not, region is null if destroyRegion executed
+      boolean readShadowKey = !msg.getDM().isLoner();
+      if (region != null) {
+        // shadowkey is not being sent to clients
+        readShadowKey = region.getPoolName() == null;
+      }
+      return readShadowKey;
+    }
+
     @Override
     public String toString() {
       StringBuilder result = new StringBuilder(64);
diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/BugTxCommitMessageDesiralizeDUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/BugTxCommitMessageDesiralizeDUnitTest.java
new file mode 100644
index 0000000..cc12083
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/cache/BugTxCommitMessageDesiralizeDUnitTest.java
@@ -0,0 +1,619 @@
+/**
+ * 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.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.CacheTransactionManager;
+import org.apache.geode.cache.DataPolicy;
+import org.apache.geode.cache.EntryOperation;
+import org.apache.geode.cache.PartitionAttributes;
+import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.PartitionResolver;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionFactory;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.client.Pool;
+import org.apache.geode.cache.client.PoolFactory;
+import org.apache.geode.cache.client.PoolManager;
+import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.internal.AvailablePort;
+import org.apache.geode.internal.Version;
+import org.apache.geode.test.dunit.Host;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
+import org.apache.geode.test.junit.categories.DistributedTest;
+
+/**
+ * This test class tests the communication pattern of a transaction for replicate and partition
+ * region. There are five VMs that two CacheServers, CacheServer with Pool and two clients. The
+ * communicate of a transaction is the following three patterns. In addition, this test class also
+ * tests transactions from older version clients to check backwards compatibility.<br>
+ * <ol>
+ * <li>CacheServer (transaction)-> CacheServer</li>
+ * <li>Client (transaction)-> CacheServer</li>
+ * <li>Old version client (transaction)-> CacheServer</li>
+ * <li>CacheServer via Pool (transaction)-> CacheServer</li>
+ * </ol>
+ */
+@Category(DistributedTest.class)
+@SuppressWarnings("serial")
+public class BugTxCommitMessageDesiralizeDUnitTest extends JUnit4DistributedTestCase {
+
+  private static VM server1 = null;
+  private static VM server2 = null;
+  private static VM server3 = null;
+  private static VM client = null;
+  private static VM oldClient = null;
+
+  private static GemFireCacheImpl cache;
+
+  private static final String REPLICATE_REGION_NAME =
+      BugTxCommitMessageDesiralizeDUnitTest.class.getSimpleName() + "_ReplicateRegion";
+  private static final String PARTITION_REGION_NAME =
+      BugTxCommitMessageDesiralizeDUnitTest.class.getSimpleName() + "_PartitionRegion";
+
+  private static String KEY1 = "KEY1";
+  private static String KEY2 = "KEY2";
+
+  @Override
+  public final void postSetUp() throws Exception {
+    disconnectFromDS();
+    Host host = Host.getHost(0);
+    server1 = host.getVM(0); // server
+    server2 = host.getVM(1); // server
+    server3 = host.getVM(2); // server with pool
+    client = host.getVM(3); // client
+    oldClient = host.getVM(4); // client old version
+
+    int port1 = server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.createServerCache());
+    int port2 = server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.createServerCache());
+    server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest
+        .createServerCacheWithPool(host.getHostName(), new Integer[] {port1, port2}));
+    client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.createClientCache(host.getHostName(),
+        new Integer[] {port1, port2}, false));
+    oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest
+        .createClientCache(host.getHostName(), new Integer[] {port1, port2}, true));
+  }
+
+  @Override
+  public final void preTearDown() throws Exception {
+    closeCache();
+
+    server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.closeCache());
+    server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.closeCache());
+    server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.closeCache());
+    client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.closeCache());
+    oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.closeCache());
+  }
+
+  public static void closeCache() throws Exception {
+    if (cache != null) {
+      cache.close();
+    }
+  }
+
+  @SuppressWarnings("deprecation")
+  public static int createServerCache() throws Exception {
+    Properties props = new Properties();
+    BugTxCommitMessageDesiralizeDUnitTest test = new BugTxCommitMessageDesiralizeDUnitTest();
+    DistributedSystem ds = test.getSystem(props);
+    ds.disconnect();
+    cache = (GemFireCacheImpl) CacheFactory.create(test.getSystem());
+
+    RegionFactory<String, String> rf1 = cache.createRegionFactory(RegionShortcut.REPLICATE);
+    rf1.create(REPLICATE_REGION_NAME);
+
+    PartitionAttributesFactory<String, Integer> paf2 = new PartitionAttributesFactory<>();
+    PartitionAttributes<String, Integer> pa2 =
+        paf2.setRedundantCopies(1).setPartitionResolver(new PartitionResolver<String, Integer>() {
+          @Override
+          public Object getRoutingObject(EntryOperation<String, Integer> opDetails) {
+            return opDetails.getKey().substring(0, 3);
+          }
+
+          @Override
+          public String getName() {
+            return getClass().getSimpleName();
+          }
+
+          @Override
+          public void close() {}
+        }).create();
+    RegionFactory<String, String> rf2 =
+        cache.createRegionFactory(RegionShortcut.PARTITION_REDUNDANT);
+    rf2.setPartitionAttributes(pa2);
+    rf2.create(PARTITION_REGION_NAME);
+
+    CacheServer server = cache.addCacheServer();
+    server.setPort(AvailablePort.getRandomAvailablePort(AvailablePort.SOCKET));
+    server.start();
+    return server.getPort();
+  }
+
+  @SuppressWarnings("deprecation")
+  public static void createServerCacheWithPool(String hostName, Integer[] ports) throws Exception {
+    Properties props = new Properties();
+    BugTxCommitMessageDesiralizeDUnitTest test = new BugTxCommitMessageDesiralizeDUnitTest();
+    DistributedSystem ds = test.getSystem(props);
+    ds.disconnect();
+    cache = (GemFireCacheImpl) CacheFactory.create(test.getSystem());
+
+    String poolName = "ClientPool";
+    PoolFactory pf = PoolManager.createFactory().setSubscriptionEnabled(true);
+    for (int port : ports) {
+      pf.addServer(hostName, port);
+    }
+    Pool pool = pf.create(poolName);
+
+    RegionFactory<String, Integer> rf1 = cache.createRegionFactory(RegionShortcut.LOCAL);
+    rf1.setDataPolicy(DataPolicy.EMPTY);
+    rf1.setPoolName(pool.getName());
+    Region<String, Integer> region1 = rf1.create(REPLICATE_REGION_NAME);
+    region1.registerInterest("ALL_KEYS");
+
+    RegionFactory<String, Integer> rf2 = cache.createRegionFactory(RegionShortcut.LOCAL);
+    rf2.setDataPolicy(DataPolicy.EMPTY);
+    rf2.setPoolName(pool.getName());
+    Region<String, Integer> region2 = rf2.create(PARTITION_REGION_NAME);
+    region2.registerInterest("ALL_KEYS");
+  }
+
+  @SuppressWarnings("deprecation")
+  public static void createClientCache(String hostName, Integer[] ports, boolean isOldVersion)
+      throws Exception {
+    Version version = null;
+    if (isOldVersion) {
+      version = Version.CURRENT;
+      setVersion("CURRENT", Version.GEODE_130);
+    }
+
+    Properties props = new Properties();
+    DistributedSystem ds = new BugTxCommitMessageDesiralizeDUnitTest().getSystem(props);
+    ds.disconnect();
+    ClientCacheFactory ccf = new ClientCacheFactory(props);
+    ccf.setPoolSubscriptionEnabled(true);
+    for (int port : ports) {
+      ccf.addPoolServer(hostName, port);
+    }
+    cache = (GemFireCacheImpl) ccf.create();
+
+    ClientRegionFactory<String, Integer> crf1 =
+        cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY);
+    Region<String, Integer> region1 = crf1.create(REPLICATE_REGION_NAME);
+    region1.registerInterest("ALL_KEYS");
+
+    ClientRegionFactory<String, Integer> crf2 =
+        cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY);
+    Region<String, Integer> region2 = crf2.create(PARTITION_REGION_NAME);
+    region2.registerInterest("ALL_KEYS");
+
+    if (isOldVersion) {
+      setVersion("CURRENT", version);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public static void doTxPuts(String regionName) throws Exception {
+    Region<String, Integer> region = cache.getRegion(regionName);
+
+    CacheTransactionManager txMngr = cache.getCacheTransactionManager();
+    txMngr.begin();
+    Integer value1 = region.get(KEY1);
+    if (value1 == null) {
+      value1 = 1;
+    } else {
+      value1++;
+    }
+    region.put(KEY1, value1);
+
+    Integer value2 = region.get(KEY2);
+    if (value2 == null) {
+      value2 = 1000;
+    } else {
+      value2++;
+    }
+    region.put(KEY2, value2);
+    txMngr.commit();
+  }
+
+  @SuppressWarnings("unchecked")
+  public static void doTxPutsBoth(String regionNameReplicate, String regionNamePartition)
+      throws Exception {
+    Region<String, Integer> regionReplicate = cache.getRegion(regionNameReplicate);
+    Region<String, Integer> regionPartition = cache.getRegion(regionNamePartition);
+
+    CacheTransactionManager txMngr = cache.getCacheTransactionManager();
+    txMngr.begin();
+    Integer valPart1 = regionPartition.get(KEY1);
+    if (valPart1 == null) {
+      valPart1 = 1500;
+    } else {
+      valPart1++;
+    }
+    regionPartition.put(KEY1, valPart1);
+
+    Integer valPart2 = regionPartition.get(KEY2);
+    if (valPart2 == null) {
+      valPart2 = 2000;
+    } else {
+      valPart2++;
+    }
+    regionPartition.put(KEY2, valPart2);
+
+    Integer valRepl1 = regionReplicate.get(KEY1);
+    if (valRepl1 == null) {
+      valRepl1 = 500;
+    } else {
+      valRepl1++;
+    }
+    regionReplicate.put(KEY1, valRepl1);
+
+    Integer valRepl2 = regionReplicate.get(KEY2);
+    if (valRepl2 == null) {
+      valRepl2 = 1000;
+    } else {
+      valRepl2++;
+    }
+    regionReplicate.put(KEY2, valRepl2);
+    txMngr.commit();
+  }
+
+  @SuppressWarnings("unchecked")
+  public static List<Integer> doGets(String regionName) throws Exception {
+    Region<String, Integer> region = cache.getRegion(regionName);
+
+    Integer value1 = region.get(KEY1);
+    Integer value2 = region.get(KEY2);
+
+    return Arrays.asList(value1, value2);
+  }
+
+  private static void setVersion(String field, Version value) throws Exception {
+    Field targetField = Version.class.getDeclaredField(field);
+    Field modifiersField = Field.class.getDeclaredField("modifiers");
+    modifiersField.setAccessible(true);
+    modifiersField.set(targetField,
+        targetField.getModifiers() & ~Modifier.PRIVATE & ~Modifier.FINAL);
+    targetField.set(null, value);
+  }
+
+  @Test
+  public void testServerToServerTxReplicate() throws Exception {
+    String regionName = REPLICATE_REGION_NAME;
+
+    List<Integer> beforeValues =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testClientToServerTxReplicate() throws Exception {
+    String regionName = REPLICATE_REGION_NAME;
+
+    List<Integer> beforeValues =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+    assertThat(afterValues3, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testOldClientToServerTxReplicate() throws Exception {
+    String regionName = REPLICATE_REGION_NAME;
+
+    List<Integer> beforeValues =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+    assertThat(afterValues3, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testServerToServerViaPoolTxReplicate() throws Exception {
+    String regionName = REPLICATE_REGION_NAME;
+
+    List<Integer> beforeValues =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+    assertThat(afterValues3, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testServerToServerTxPartition() throws Exception {
+    String regionName = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValues =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testClientToServerTxPartition() throws Exception {
+    String regionName = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValues =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+    assertThat(afterValues3, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testOldClientToServerTxPartition() throws Exception {
+    String regionName = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValues =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+    assertThat(afterValues3, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testServerToServerViaPoolTxPartition() throws Exception {
+    String regionName = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValues =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doTxPuts(regionName));
+    List<Integer> afterValues1 =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+    List<Integer> afterValues3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionName));
+
+    Integer expected1 = beforeValues.get(0) == null ? 1 : beforeValues.get(0) + 1;
+    Integer expected2 = beforeValues.get(1) == null ? 1000 : beforeValues.get(1) + 1000;
+
+    assertThat(afterValues1, contains(expected1, expected2));
+    assertThat(afterValues2, contains(expected1, expected2));
+    assertThat(afterValues3, contains(expected1, expected2));
+  }
+
+  @Test
+  public void testServerToServerTxBoth() throws Exception {
+    String regionNameRepl = REPLICATE_REGION_NAME;
+    String regionNamePart = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValuesRepl =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> beforeValuesPart =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    server1.invoke(
+        () -> BugTxCommitMessageDesiralizeDUnitTest.doTxPutsBoth(regionNameRepl, regionNamePart));
+    List<Integer> afterValuesRepl1 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesRepl2 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart1 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesPart2 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+
+    Integer expectedRepl1 = beforeValuesRepl.get(0) == null ? 500 : beforeValuesRepl.get(0) + 500;
+    Integer expectedRepl2 = beforeValuesRepl.get(1) == null ? 1000 : beforeValuesRepl.get(1) + 1000;
+    Integer expectedPart1 = beforeValuesPart.get(0) == null ? 1500 : beforeValuesPart.get(0) + 1500;
+    Integer expectedPart2 = beforeValuesPart.get(1) == null ? 2000 : beforeValuesPart.get(1) + 2000;
+
+    assertThat(afterValuesRepl1, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesRepl2, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart1, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesPart2, contains(expectedPart1, expectedPart2));
+  }
+
+  @Test
+  public void testClientToServerTxBoth() throws Exception {
+    String regionNameRepl = REPLICATE_REGION_NAME;
+    String regionNamePart = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValuesRepl =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> beforeValuesPart =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    client.invoke(
+        () -> BugTxCommitMessageDesiralizeDUnitTest.doTxPutsBoth(regionNameRepl, regionNamePart));
+    List<Integer> afterValuesRepl1 =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart1 =
+        client.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesRepl2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesRepl3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+
+    Integer expectedRepl1 = beforeValuesRepl.get(0) == null ? 500 : beforeValuesRepl.get(0) + 500;
+    Integer expectedRepl2 = beforeValuesRepl.get(1) == null ? 1000 : beforeValuesRepl.get(1) + 1000;
+    Integer expectedPart1 = beforeValuesPart.get(0) == null ? 1500 : beforeValuesPart.get(0) + 1500;
+    Integer expectedPart2 = beforeValuesPart.get(1) == null ? 2000 : beforeValuesPart.get(1) + 2000;
+
+    assertThat(afterValuesRepl1, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart1, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesRepl2, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart2, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesRepl3, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart3, contains(expectedPart1, expectedPart2));
+  }
+
+  @Test
+  public void testOldClientToServerTxBoth() throws Exception {
+    String regionNameRepl = REPLICATE_REGION_NAME;
+    String regionNamePart = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValuesRepl =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> beforeValuesPart =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    oldClient.invoke(
+        () -> BugTxCommitMessageDesiralizeDUnitTest.doTxPutsBoth(regionNameRepl, regionNamePart));
+    List<Integer> afterValuesRepl1 =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart1 =
+        oldClient.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesRepl2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesRepl3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+
+    Integer expectedRepl1 = beforeValuesRepl.get(0) == null ? 500 : beforeValuesRepl.get(0) + 500;
+    Integer expectedRepl2 = beforeValuesRepl.get(1) == null ? 1000 : beforeValuesRepl.get(1) + 1000;
+    Integer expectedPart1 = beforeValuesPart.get(0) == null ? 1500 : beforeValuesPart.get(0) + 1500;
+    Integer expectedPart2 = beforeValuesPart.get(1) == null ? 2000 : beforeValuesPart.get(1) + 2000;
+
+    assertThat(afterValuesRepl1, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart1, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesRepl2, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart2, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesRepl3, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart3, contains(expectedPart1, expectedPart2));
+  }
+
+  @Test
+  public void testServerToServerViaPoolTxBoth() throws Exception {
+    String regionNameRepl = REPLICATE_REGION_NAME;
+    String regionNamePart = PARTITION_REGION_NAME;
+
+    List<Integer> beforeValuesRepl =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> beforeValuesPart =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    server3.invoke(
+        () -> BugTxCommitMessageDesiralizeDUnitTest.doTxPutsBoth(regionNameRepl, regionNamePart));
+    List<Integer> afterValuesRepl1 =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart1 =
+        server3.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesRepl2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart2 =
+        server1.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+    List<Integer> afterValuesRepl3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNameRepl));
+    List<Integer> afterValuesPart3 =
+        server2.invoke(() -> BugTxCommitMessageDesiralizeDUnitTest.doGets(regionNamePart));
+
+    Integer expectedRepl1 = beforeValuesRepl.get(0) == null ? 500 : beforeValuesRepl.get(0) + 500;
+    Integer expectedRepl2 = beforeValuesRepl.get(1) == null ? 1000 : beforeValuesRepl.get(1) + 1000;
+    Integer expectedPart1 = beforeValuesPart.get(0) == null ? 1500 : beforeValuesPart.get(0) + 1500;
+    Integer expectedPart2 = beforeValuesPart.get(1) == null ? 2000 : beforeValuesPart.get(1) + 2000;
+
+    assertThat(afterValuesRepl1, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart1, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesRepl2, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart2, contains(expectedPart1, expectedPart2));
+    assertThat(afterValuesRepl3, contains(expectedRepl1, expectedRepl2));
+    assertThat(afterValuesPart3, contains(expectedPart1, expectedPart2));
+  }
+}
diff --git a/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt b/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
index 1c5a36d..1a51bd0 100644
--- a/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
+++ b/geode-core/src/test/resources/org/apache/geode/codeAnalysis/sanctionedDataSerializables.txt
@@ -1334,7 +1334,7 @@ fromData,16,2a2bb700042a2bb900050100b50002b1
 toData,16,2a2bb700062b2ab40002b900070200b1
 
 org/apache/geode/internal/cache/TXCommitMessage$RegionCommit,2
-fromData,181,2a2bb80058b5000b2a2bb80058b500202bb9005901003d1c9e009c2abb0053591cb70054b500512abb0053591cb70054b500552bb9005a01003e2a2bb8005bc0005cb5005d03360415041ca20069bb005e592ab7005f3a0519052b1d2ab40002b60060b9006101009a000704a7000403b600621905b80032c600162ab4005dc6000f1905b800322ab4005db600632ab400021905b600642ab400511905b4002cb60056572ab400551905b6005657840401a7ff97b1
+fromData,173,2a2bb8005ab5000b2a2bb8005ab5001f2bb9005b01003d1c9e00942abb0055591cb70056b500532abb0055591cb70056b500572bb9005c01003e2a2bb8005dc0005eb5005f03360415041ca20061bb0060592ab700613a0519052b1d2a2ab4000b2ab4001fb70062b600631905b80034c600162ab4005fc6000f1905b800342ab4005fb600642ab400021905b600652ab400531905b4002eb60058572ab400571905b6005857840401a7ff9fb1
 toData,77,2ab40005c600152ab40005b600832ab400052bb60084a700362ab4000404a400292bb800854dbb0086591104002cb700874e2a2db700882a2db500052ab400052bb60084a700082a2bb70088b1
 
 org/apache/geode/internal/cache/TXCommitMessage$RegionCommit$FarSideEntryOp,2

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