@Test
  public void testInternalCallbacks() throws Exception {
    final CacheTransactionManager txMgr = getCache().getCacheTransactionManager();
    final String rgnName1 = getUniqueName() + "_1";
    final String rgnName2 = getUniqueName() + "_2";
    final String rgnName3 = getUniqueName() + "_3";
    Region rgn1 = getCache().createRegion(rgnName1, getRegionAttributes());

    Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);

    SerializableRunnable createRgn =
        new SerializableRunnable("testInternalCallbacks: initial configuration") {
          @Override
          public void run() {
            try {
              Region rgn1a = getCache().createRegion(rgnName1, getRegionAttributes());
              Region rgn2 = getCache().createRegion(rgnName2, getRegionAttributes());
              Region rgn3 =
                  getCache().createRegion(rgnName3, getRegionAttributes(Scope.DISTRIBUTED_NO_ACK));
              rgn1a.create("key", null);
              rgn2.create("key", null);
              rgn3.create("key", null);
            } catch (CacheException e) {
              Assert.fail("While creating region", e);
            }
          }
        };
    vm0.invoke(createRgn);
    vm1.invoke(createRgn);

    // Standard commit check
    txMgr.begin();
    rgn1.put("key", "value0");
    txMgr.commit();
    SerializableRunnable checkRgn1 =
        new SerializableRunnable("testInternalCallbacks: check rgn1 valus") {
          @Override
          public void run() {
            Region rgn1a = getCache().getRegion(rgnName1);
            assertNotNull(rgn1a);
            assertEquals("value0", rgn1a.getEntry("key").getValue());
          }
        };
    vm0.invoke(checkRgn1);
    vm1.invoke(checkRgn1);

    {
      final byte[] cbSensors = {0, 0, 0, 0, 0, 0, 0, 0, 0};
      txMgr.begin();
      ((TXStateProxyImpl) ((TXManagerImpl) txMgr).getTXState()).forceLocalBootstrap();
      setInternalCallbacks(((TXManagerImpl) txMgr).getTXState(), cbSensors);
      rgn1.put("key", "value1");
      txMgr.commit();
      for (int i = cbSensors.length - 3; i >= 0; --i) {
        assertEquals("Internal callback " + i + " was not called the expected number of times!",
            (byte) 1, cbSensors[i]);
      }
      for (int i = cbSensors.length - 1; i > cbSensors.length - 3; --i) {
        assertEquals(
            "Internal \"during\" callback " + i + " invoked an unexpected number of times!",
            (byte) 2, cbSensors[i]);
      }
    }
    SerializableRunnable checkRgn1Again =
        new SerializableRunnable("testInternalCallbacks: validate remote values") {
          @Override
          public void run() {
            Region rgn1a = getCache().getRegion(rgnName1);
            assertNotNull(rgn1a);
            assertEquals("value1", rgn1a.getEntry("key").getValue());
          }
        };
    vm0.invoke(checkRgn1Again);
    vm1.invoke(checkRgn1Again);

    // Try 2 regions
    Region rgn2 = getCache().createRegion(rgnName2, getRegionAttributes());
    txMgr.begin();
    rgn1.put("key", "value2");
    rgn2.put("key", "value2");
    txMgr.commit();
    SerializableRunnable checkRgn12 =
        new SerializableRunnable("testInternalCallbacks: check rgn1 valus") {
          @Override
          public void run() {
            Region rgn1a = getCache().getRegion(rgnName1);
            assertNotNull(rgn1a);
            assertEquals("value2", rgn1a.getEntry("key").getValue());
            Region rgn2a = getCache().getRegion(rgnName2);
            assertNotNull(rgn2a);
            assertEquals("value2", rgn2a.getEntry("key").getValue());
          }
        };
    vm0.invoke(checkRgn12);
    vm1.invoke(checkRgn12);

    {
      final byte[] cbSensors = {0, 0, 0, 0, 0, 0, 0, 0, 0};
      txMgr.begin();
      ((TXStateProxyImpl) ((TXManagerImpl) txMgr).getTXState()).forceLocalBootstrap();
      setInternalCallbacks(((TXManagerImpl) txMgr).getTXState(), cbSensors);
      rgn1.put("key", "value3");
      rgn2.put("key", "value3");
      txMgr.commit();

      for (int i = cbSensors.length - 3; i >= 0; i--) {
        assertEquals("Internal callback " + i + " was not called the expected number of times!",
            (byte) 1, cbSensors[i]);
      }
      for (int i = cbSensors.length - 1; i > cbSensors.length - 3; --i) {
        assertEquals(
            "Internal \"during\" callback " + i + " invoked an unexpected number of times!",
            (byte) 2, cbSensors[i]);
      }
    }
    SerializableRunnable checkRgn12Again =
        new SerializableRunnable("testInternalCallbacks: validate both regions remote values") {
          @Override
          public void run() {
            Region rgn1a = getCache().getRegion(rgnName1);
            assertNotNull(rgn1a);
            assertEquals("value3", rgn1a.getEntry("key").getValue());
            Region rgn2a = getCache().getRegion(rgnName2);
            assertNotNull(rgn2a);
            assertEquals("value3", rgn2a.getEntry("key").getValue());
          }
        };
    vm0.invoke(checkRgn12Again);
    vm1.invoke(checkRgn12Again);

    // Try a third region (D_NO_ACK)
    Region rgn3 = getCache().createRegion(rgnName3, getRegionAttributes(Scope.DISTRIBUTED_NO_ACK));
    txMgr.begin();
    rgn1.put("key", "value4");
    rgn2.put("key", "value4");
    rgn3.put("key", "value4");
    txMgr.commit();
    SerializableRunnable checkRgn123 =
        new SerializableRunnable("testInternalCallbacks: check rgn1 valus") {
          @Override
          public void run() {
            Region rgn1a = getCache().getRegion(rgnName1);
            assertNotNull(rgn1a);
            assertEquals("value4", rgn1a.getEntry("key").getValue());
            Region rgn2a = getCache().getRegion(rgnName2);
            assertNotNull(rgn2a);
            assertEquals("value4", rgn2a.getEntry("key").getValue());
            Region rgn3a = getCache().getRegion(rgnName3);
            assertNotNull(rgn3a);
            assertEquals("value4", rgn3a.getEntry("key").getValue());
          }
        };
    vm0.invoke(checkRgn123);
    vm1.invoke(checkRgn123);

    {
      final byte[] cbSensors = {0, 0, 0, 0, 0, 0, 0, 0, 0};
      txMgr.begin();
      ((TXStateProxyImpl) ((TXManagerImpl) txMgr).getTXState()).forceLocalBootstrap();
      setInternalCallbacks(((TXManagerImpl) txMgr).getTXState(), cbSensors);

      rgn1.put("key", "value5");
      rgn2.put("key", "value5");
      rgn3.put("key", "value5");
      txMgr.commit();

      for (int i = cbSensors.length - 3; i >= 0; i--) {
        assertEquals("Internal callback " + i + " was not called the expected number of times!",
            (byte) 1, cbSensors[i]);
      }
      for (int i = cbSensors.length - 1; i > cbSensors.length - 3; --i) {
        assertEquals(
            "Internal \"during\" callback " + i + " invoked an unexpected number of times!",
            (byte) 2, cbSensors[i]);
      }
    }
    SerializableRunnable checkRgn123Again =
        new SerializableRunnable("testInternalCallbacks: validate both regions remote values") {
          @Override
          public void run() {
            Region rgn1a = getCache().getRegion(rgnName1);
            assertNotNull(rgn1a);
            assertEquals("value5", rgn1a.getEntry("key").getValue());
            Region rgn2a = getCache().getRegion(rgnName2);
            assertNotNull(rgn2a);
            assertEquals("value5", rgn2a.getEntry("key").getValue());
            Region rgn3a = getCache().getRegion(rgnName3);
            assertNotNull(rgn3a);
            assertEquals("value5", rgn3a.getEntry("key").getValue());
          }
        };
    vm0.invoke(checkRgn123Again);
    vm1.invoke(checkRgn123Again);

    rgn1.destroyRegion();
    rgn2.destroyRegion();
  }
Test the internal callbacks used for what else... testing
geode-core/src/distributedTest/java/org/apache/geode/cache30/TXDistributedDUnitTest.java