private void evictOrRemoveTest(boolean evict) {

    final String KEY = KEY_BASE + testCount++;

    assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
    assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));

    localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
    assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
    remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
    assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));

    // Wait for async propagation
    sleep(250);

    if (evict) {
      localAccessStrategy.evict(KEY);
    } else {
      localAccessStrategy.remove(KEY);
    }

    assertEquals(null, localAccessStrategy.get(KEY, System.currentTimeMillis()));

    assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
  }
  private void evictOrRemoveAllTest(boolean evict) {

    final String KEY = KEY_BASE + testCount++;

    assertEquals(0, getValidKeyCount(localCollectionRegion.getCacheAdapter().keySet()));

    assertEquals(0, getValidKeyCount(remoteCollectionRegion.getCacheAdapter().keySet()));

    assertNull("local is clean", localAccessStrategy.get(KEY, System.currentTimeMillis()));
    assertNull("remote is clean", remoteAccessStrategy.get(KEY, System.currentTimeMillis()));

    localAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
    assertEquals(VALUE1, localAccessStrategy.get(KEY, System.currentTimeMillis()));
    remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
    assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));

    // Wait for async propagation
    sleep(250);

    if (evict) {
      localAccessStrategy.evictAll();
    } else {
      localAccessStrategy.removeAll();
    }

    // This should re-establish the region root node
    assertNull(localAccessStrategy.get(KEY, System.currentTimeMillis()));

    assertEquals(0, getValidKeyCount(localCollectionRegion.getCacheAdapter().keySet()));

    // Re-establishing the region root on the local node doesn't
    // propagate it to other nodes. Do a get on the remote node to re-establish
    assertEquals(null, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));

    assertEquals(0, getValidKeyCount(remoteCollectionRegion.getCacheAdapter().keySet()));

    // Test whether the get above messes up the optimistic version
    remoteAccessStrategy.putFromLoad(KEY, VALUE1, System.currentTimeMillis(), new Integer(1));
    assertEquals(VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));

    assertEquals(1, getValidKeyCount(remoteCollectionRegion.getCacheAdapter().keySet()));

    // Wait for async propagation of the putFromLoad
    sleep(250);

    assertEquals(
        "local is correct",
        (isUsingInvalidation() ? null : VALUE1),
        localAccessStrategy.get(KEY, System.currentTimeMillis()));
    assertEquals(
        "remote is correct", VALUE1, remoteAccessStrategy.get(KEY, System.currentTimeMillis()));
  }
 @Test
 public void testGetRegion() {
   assertEquals("Correct region", localCollectionRegion, localAccessStrategy.getRegion());
 }
  private void putFromLoadTest(final boolean useMinimalAPI) throws Exception {

    final String KEY = KEY_BASE + testCount++;

    final CountDownLatch writeLatch1 = new CountDownLatch(1);
    final CountDownLatch writeLatch2 = new CountDownLatch(1);
    final CountDownLatch completionLatch = new CountDownLatch(2);

    Thread node1 =
        new Thread() {

          public void run() {

            try {
              long txTimestamp = System.currentTimeMillis();
              BatchModeTransactionManager.getInstance().begin();

              assertEquals("node1 starts clean", null, localAccessStrategy.get(KEY, txTimestamp));

              writeLatch1.await();

              if (useMinimalAPI) {
                localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2), true);
              } else {
                localAccessStrategy.putFromLoad(KEY, VALUE2, txTimestamp, new Integer(2));
              }

              BatchModeTransactionManager.getInstance().commit();
            } catch (Exception e) {
              log.error("node1 caught exception", e);
              node1Exception = e;
              rollback();
            } catch (AssertionFailedError e) {
              node1Failure = e;
              rollback();
            } finally {
              // Let node2 write
              writeLatch2.countDown();
              completionLatch.countDown();
            }
          }
        };

    Thread node2 =
        new Thread() {

          public void run() {

            try {
              long txTimestamp = System.currentTimeMillis();
              BatchModeTransactionManager.getInstance().begin();

              assertNull("node2 starts clean", remoteAccessStrategy.get(KEY, txTimestamp));

              // Let node1 write
              writeLatch1.countDown();
              // Wait for node1 to finish
              writeLatch2.await();

              // Let the first PFER propagate
              sleep(200);

              if (useMinimalAPI) {
                remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1), true);
              } else {
                remoteAccessStrategy.putFromLoad(KEY, VALUE1, txTimestamp, new Integer(1));
              }

              BatchModeTransactionManager.getInstance().commit();
            } catch (Exception e) {
              log.error("node2 caught exception", e);
              node2Exception = e;
              rollback();
            } catch (AssertionFailedError e) {
              node2Failure = e;
              rollback();
            } finally {
              completionLatch.countDown();
            }
          }
        };

    node1.setDaemon(true);
    node2.setDaemon(true);

    node1.start();
    node2.start();

    assertTrue("Threads completed", completionLatch.await(2, TimeUnit.SECONDS));

    if (node1Failure != null) {
      throw node1Failure;
    }
    if (node2Failure != null) {
      throw node2Failure;
    }

    assertEquals("node1 saw no exceptions", null, node1Exception);
    assertEquals("node2 saw no exceptions", null, node2Exception);

    // let the final PFER propagate
    sleep(100);

    long txTimestamp = System.currentTimeMillis();
    String msg1 = "Correct node1 value";
    String msg2 = "Correct node2 value";
    Object expected1 = null;
    Object expected2 = null;
    if (isUsingInvalidation()) {
      // PFER does not generate any invalidation, so each node should
      // succeed. We count on database locking and Hibernate removing
      // the collection on any update to prevent the situation we have
      // here where the caches have inconsistent data
      expected1 = VALUE2;
      expected2 = VALUE1;
    } else {
      // the initial VALUE2 should prevent the node2 put
      expected1 = VALUE2;
      expected2 = VALUE2;
    }

    assertEquals(msg1, expected1, localAccessStrategy.get(KEY, txTimestamp));
    assertEquals(msg2, expected2, remoteAccessStrategy.get(KEY, txTimestamp));
  }
 @Override
 protected void putInRegion(Region region, Object key, Object value) {
   CollectionRegionAccessStrategy strategy =
       ((CollectionRegion) region).buildAccessStrategy(AccessType.TRANSACTIONAL);
   strategy.putFromLoad(key, value, System.currentTimeMillis(), new Integer(1));
 }