| /* |
| * 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; |
| |
| import static org.apache.geode.cache.Region.SEPARATOR; |
| import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT; |
| import static org.assertj.core.api.Assertions.assertThat; |
| import static org.assertj.core.api.Assertions.assertThatThrownBy; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.NoSuchElementException; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import javax.transaction.Synchronization; |
| |
| import org.junit.After; |
| import org.junit.AfterClass; |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.rules.TestName; |
| |
| import org.apache.geode.cache.AttributesFactory; |
| import org.apache.geode.cache.AttributesMutator; |
| import org.apache.geode.cache.Cache; |
| import org.apache.geode.cache.CacheEvent; |
| import org.apache.geode.cache.CacheException; |
| import org.apache.geode.cache.CacheFactory; |
| import org.apache.geode.cache.CacheListener; |
| import org.apache.geode.cache.CacheLoader; |
| import org.apache.geode.cache.CacheLoaderException; |
| import org.apache.geode.cache.CacheTransactionManager; |
| import org.apache.geode.cache.CacheWriter; |
| import org.apache.geode.cache.CacheWriterException; |
| import org.apache.geode.cache.CommitConflictException; |
| import org.apache.geode.cache.DataPolicy; |
| import org.apache.geode.cache.DiskStoreFactory; |
| import org.apache.geode.cache.EntryEvent; |
| import org.apache.geode.cache.EntryExistsException; |
| import org.apache.geode.cache.EntryNotFoundException; |
| import org.apache.geode.cache.EvictionAction; |
| import org.apache.geode.cache.EvictionAttributes; |
| import org.apache.geode.cache.FailedSynchronizationException; |
| import org.apache.geode.cache.LoaderHelper; |
| import org.apache.geode.cache.PartitionAttributes; |
| import org.apache.geode.cache.PartitionAttributesFactory; |
| import org.apache.geode.cache.Region; |
| import org.apache.geode.cache.RegionEvent; |
| import org.apache.geode.cache.RegionFactory; |
| import org.apache.geode.cache.RegionShortcut; |
| import org.apache.geode.cache.Scope; |
| import org.apache.geode.cache.TimeoutException; |
| import org.apache.geode.cache.TransactionEvent; |
| import org.apache.geode.cache.TransactionException; |
| import org.apache.geode.cache.TransactionId; |
| import org.apache.geode.cache.TransactionListener; |
| import org.apache.geode.cache.UnsupportedOperationInTransactionException; |
| import org.apache.geode.cache.query.Index; |
| import org.apache.geode.cache.query.IndexType; |
| import org.apache.geode.cache.query.Query; |
| import org.apache.geode.cache.query.QueryException; |
| import org.apache.geode.cache.query.QueryService; |
| import org.apache.geode.cache.query.SelectResults; |
| import org.apache.geode.cache.query.internal.index.IndexManager; |
| import org.apache.geode.cache.util.CacheListenerAdapter; |
| import org.apache.geode.cache.util.TransactionListenerAdapter; |
| import org.apache.geode.cache.util.TxEventTestUtil; |
| import org.apache.geode.distributed.DistributedSystem; |
| import org.apache.geode.distributed.internal.InternalDistributedSystem; |
| import org.apache.geode.internal.NanoTimer; |
| import org.apache.geode.internal.cache.AbstractRegion; |
| import org.apache.geode.internal.cache.CachePerfStats; |
| import org.apache.geode.internal.cache.GemFireCacheImpl; |
| import org.apache.geode.internal.cache.LocalRegion; |
| import org.apache.geode.internal.cache.NonTXEntry; |
| import org.apache.geode.internal.cache.PartitionedRegion; |
| import org.apache.geode.internal.cache.TXManagerImpl; |
| import org.apache.geode.internal.cache.TXStateProxy; |
| import org.apache.geode.internal.util.StopWatch; |
| import org.apache.geode.logging.internal.log4j.api.LogService; |
| import org.apache.geode.util.internal.GeodeGlossary; |
| |
| /** |
| * Tests basic transaction functionality |
| * |
| * @since GemFire 4.0 |
| */ |
| @SuppressWarnings("deprecated") |
| public class TXJUnitTest { |
| |
| private int cbCount; |
| private TransactionEvent te; |
| |
| protected int listenerAfterCommit; |
| protected int listenerAfterFailedCommit; |
| protected int listenerAfterRollback; |
| protected int listenerClose; |
| protected CacheTransactionManager txMgr; |
| |
| protected GemFireCacheImpl cache; |
| protected Region<String, String> region; |
| |
| @Rule |
| public TestName testName = new TestName(); |
| |
| private boolean isPR() { |
| return (this.region instanceof PartitionedRegion); |
| } |
| |
| protected void createCache() throws Exception { |
| Properties properties = new Properties(); |
| properties.setProperty(MCAST_PORT, "0"); // loner |
| |
| this.cache = (GemFireCacheImpl) CacheFactory.create(DistributedSystem.connect(properties)); |
| |
| createRegion(); |
| this.txMgr = this.cache.getCacheTransactionManager(); |
| this.listenerAfterCommit = 0; |
| this.listenerAfterFailedCommit = 0; |
| this.listenerAfterRollback = 0; |
| this.listenerClose = 0; |
| } |
| |
| protected void createRegion() throws Exception { |
| region = createRegion(getClass().getSimpleName(), false); |
| } |
| |
| protected Region createRegion(String regionName, boolean isConcurrencyChecksEnabled) |
| throws Exception { |
| AttributesFactory<String, String> attributesFactory = new AttributesFactory<>(); |
| attributesFactory |
| .setDataPolicy(isConcurrencyChecksEnabled ? DataPolicy.REPLICATE : DataPolicy.NORMAL); |
| attributesFactory |
| .setScope(isConcurrencyChecksEnabled ? Scope.DISTRIBUTED_ACK : Scope.DISTRIBUTED_NO_ACK); |
| attributesFactory.setConcurrencyChecksEnabled(isConcurrencyChecksEnabled); // test validation |
| // expects this |
| // behavior |
| attributesFactory.setIndexMaintenanceSynchronous(true); |
| |
| return this.cache.createRegion(regionName, attributesFactory.create()); |
| } |
| |
| protected void closeCache() { |
| if (this.cache != null) { |
| if (this.txMgr != null) { |
| try { |
| this.txMgr.rollback(); |
| } catch (IllegalStateException ignore) { |
| } |
| } |
| this.region = null; |
| this.txMgr = null; |
| Cache c = this.cache; |
| this.cache = null; |
| c.close(); |
| } |
| } |
| |
| @Before |
| public void setUpTXJUnitTest() throws Exception { |
| createCache(); |
| } |
| |
| @After |
| public void tearDownTXJUnitTest() throws Exception { |
| closeCache(); |
| } |
| |
| @AfterClass |
| public static void afterClass() { |
| InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance(); |
| if (ids != null) { |
| ids.disconnect(); |
| } |
| } |
| |
| private void checkNoTxState() { |
| assertEquals(null, this.txMgr.getTransactionId()); |
| assertTrue(!this.txMgr.exists()); |
| try { |
| this.txMgr.commit(); |
| fail("expected IllegalStateException"); |
| } catch (CommitConflictException unexpected) { |
| fail("did not expect " + unexpected); |
| } catch (IllegalStateException expected) { |
| } |
| try { |
| this.txMgr.rollback(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| } |
| |
| @Test |
| public void testSimpleOps() throws CacheException { |
| final CachePerfStats stats = this.cache.getCachePerfStats(); |
| // See if things are ok when no transaction |
| checkNoTxState(); |
| |
| this.txMgr.begin(); |
| // now that a transaction exists make sure things behave as expected |
| assertTrue(this.txMgr.getTransactionId() != null); |
| assertTrue(this.txMgr.exists()); |
| try { |
| this.txMgr.begin(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| try { |
| this.txMgr.commit(); |
| } catch (CommitConflictException unexpected) { |
| fail("did not expect " + unexpected); |
| } |
| checkNoTxState(); |
| |
| this.txMgr.begin(); |
| this.txMgr.rollback(); |
| checkNoTxState(); |
| |
| this.region.put("uaKey", "val"); |
| |
| { |
| Region.Entry cmtre = this.region.getEntry("uaKey"); |
| cmtre.setUserAttribute("uaValue1"); |
| assertEquals("uaValue1", cmtre.getUserAttribute()); |
| |
| int txRollbackChanges = stats.getTxRollbackChanges(); |
| int txCommitChanges = stats.getTxCommitChanges(); |
| int txFailureChanges = stats.getTxFailureChanges(); |
| this.txMgr.begin(); |
| Region.Entry txre = this.region.getEntry("uaKey"); |
| assertEquals(this.region, txre.getRegion()); |
| if (isPR()) { |
| this.region.put("1", "one"); |
| try { |
| txre.setUserAttribute("uaValue2"); |
| } catch (UnsupportedOperationException e) { |
| // expected |
| } |
| try { |
| txre.getUserAttribute(); |
| } catch (UnsupportedOperationException e) { |
| // expected |
| } |
| } else { |
| assertEquals("uaValue1", txre.getUserAttribute()); |
| txre.setUserAttribute("uaValue2"); |
| assertEquals("uaValue2", txre.getUserAttribute()); |
| } |
| this.txMgr.rollback(); |
| try { |
| txre.getValue(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txre.isDestroyed(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txre.getUserAttribute(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txre.setUserAttribute("foo"); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| assertEquals(txCommitChanges, stats.getTxCommitChanges()); |
| assertEquals(txFailureChanges, stats.getTxFailureChanges()); |
| |
| assertEquals("uaValue1", cmtre.getUserAttribute()); |
| } |
| |
| { |
| int txRollbackChanges = stats.getTxRollbackChanges(); |
| int txCommitChanges = stats.getTxCommitChanges(); |
| int txFailureChanges = stats.getTxFailureChanges(); |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(this.region.get("key1"), "value1"); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| assertEquals(txCommitChanges, stats.getTxCommitChanges()); |
| assertEquals(txFailureChanges, stats.getTxFailureChanges()); |
| |
| txRollbackChanges = stats.getTxRollbackChanges(); |
| this.txMgr.begin(); |
| this.region.destroy("key1"); |
| this.txMgr.rollback(); |
| assertEquals(this.region.get("key1"), "value1"); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| assertEquals(txCommitChanges, stats.getTxCommitChanges()); |
| assertEquals(txFailureChanges, stats.getTxFailureChanges()); |
| |
| txRollbackChanges = stats.getTxRollbackChanges(); |
| this.txMgr.begin(); |
| this.region.put("key1", "value2"); |
| this.txMgr.rollback(); |
| assertEquals(this.region.get("key1"), "value1"); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| assertEquals(txCommitChanges, stats.getTxCommitChanges()); |
| assertEquals(txFailureChanges, stats.getTxFailureChanges()); |
| } |
| } |
| |
| @Test |
| public void testWriteOps() throws CacheException { |
| this.txMgr.begin(); |
| this.region.put("key1", "value1"); |
| this.region.put("key2", "value2"); |
| assertTrue(this.region.containsKey("key1")); |
| assertTrue(this.region.containsValueForKey("key1")); |
| assertEquals("key1", this.region.getEntry("key1").getKey()); |
| assertEquals("value1", this.region.getEntry("key1").getValue()); |
| assertEquals("value1", this.region.get("key1")); |
| assertTrue(this.region.containsKey("key2")); |
| assertTrue(this.region.containsValueForKey("key2")); |
| assertEquals("key2", this.region.getEntry("key2").getKey()); |
| assertEquals("value2", this.region.getEntry("key2").getValue()); |
| assertEquals("value2", this.region.get("key2")); |
| this.txMgr.rollback(); |
| assertTrue(!this.region.containsKey("key1")); |
| assertTrue(!this.region.containsKey("key2")); |
| |
| this.txMgr.begin(); |
| this.region.create("key1", "value1"); |
| assertTrue(this.region.containsKey("key1")); |
| assertTrue(this.region.containsValueForKey("key1")); |
| assertEquals("key1", this.region.getEntry("key1").getKey()); |
| assertEquals("value1", this.region.getEntry("key1").getValue()); |
| assertEquals("value1", this.region.get("key1")); |
| this.txMgr.rollback(); |
| assertTrue(!this.region.containsKey("key1")); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.put("key1", "value2"); |
| this.txMgr.rollback(); |
| assertTrue(this.region.containsKey("key1")); |
| assertEquals("value1", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.localDestroy("key1"); |
| assertTrue(!this.region.containsKey("key1")); |
| assertTrue(!this.region.containsValueForKey("key1")); |
| this.txMgr.rollback(); |
| assertTrue(this.region.containsKey("key1")); |
| this.region.localDestroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.destroy("key1"); |
| assertTrue(!this.region.containsKey("key1")); |
| assertTrue(!this.region.containsValueForKey("key1")); |
| this.txMgr.rollback(); |
| assertTrue(this.region.containsKey("key1")); |
| this.region.localDestroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| assertTrue(this.region.containsValueForKey("key1")); |
| this.region.localInvalidate("key1"); |
| assertTrue(this.region.containsKey("key1")); |
| assertTrue(!this.region.containsValueForKey("key1")); |
| assertEquals(null, this.region.get("key1")); |
| this.txMgr.rollback(); |
| assertTrue(this.region.containsValueForKey("key1")); |
| this.region.localDestroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| assertTrue(this.region.containsValueForKey("key1")); |
| this.region.invalidate("key1"); |
| assertTrue(this.region.containsKey("key1")); |
| assertTrue(!this.region.containsValueForKey("key1")); |
| assertEquals(null, this.region.get("key1")); |
| this.txMgr.rollback(); |
| assertTrue(this.region.containsValueForKey("key1")); |
| this.region.localDestroy("key1"); |
| |
| // see if commits work |
| assertTrue(!this.region.containsKey("key1")); |
| assertTrue(!this.region.containsKey("key2")); |
| this.txMgr.begin(); |
| this.region.create("key1", "value1"); |
| this.region.create("key2", "value2"); |
| this.txMgr.commit(); |
| assertTrue(this.region.containsKey("key1")); |
| assertTrue(this.region.containsValueForKey("key1")); |
| assertEquals("key1", this.region.getEntry("key1").getKey()); |
| assertEquals("value1", this.region.getEntry("key1").getValue()); |
| assertEquals("value1", this.region.get("key1")); |
| assertTrue(this.region.containsKey("key2")); |
| assertTrue(this.region.containsValueForKey("key2")); |
| assertEquals("key2", this.region.getEntry("key2").getKey()); |
| assertEquals("value2", this.region.getEntry("key2").getValue()); |
| assertEquals("value2", this.region.get("key2")); |
| this.region.localDestroy("key1"); |
| this.region.localDestroy("key2"); |
| } |
| |
| @Test |
| public void testTwoRegionTxs() throws CacheException { |
| final CachePerfStats stats = this.cache.getCachePerfStats(); |
| int txCommitChanges; |
| TransactionId myTxId; |
| |
| AttributesFactory<String, String> attributesFactory = new AttributesFactory<>(); |
| attributesFactory.setScope(Scope.DISTRIBUTED_NO_ACK); |
| |
| Region<String, String> reg1 = this.region; |
| Region<String, String> reg2 = |
| this.cache.createRegion(getUniqueName(), attributesFactory.create()); |
| |
| this.txMgr.setListener(new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| listenerAfterCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| listenerAfterFailedCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| listenerAfterRollback = 1; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| listenerClose = 1; |
| } |
| }); |
| |
| // see if commits work |
| txCommitChanges = stats.getTxCommitChanges(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertTrue(!reg2.containsKey("key2")); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value1"); |
| reg2.create("key2", "value2"); |
| this.txMgr.commit(); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(reg1.containsValueForKey("key1")); |
| assertEquals("key1", reg1.getEntry("key1").getKey()); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| assertEquals("value1", reg1.get("key1")); |
| assertTrue(reg2.containsKey("key2")); |
| assertTrue(reg2.containsValueForKey("key2")); |
| assertEquals("key2", reg2.getEntry("key2").getKey()); |
| assertEquals("value2", reg2.getEntry("key2").getValue()); |
| assertEquals("value2", reg2.get("key2")); |
| assertEquals(txCommitChanges + 2, stats.getTxCommitChanges()); |
| { |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(2, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1 || ev.getRegion() == reg2); |
| if (ev.getRegion() == reg1) { |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| } else { |
| assertEquals("key2", ev.getKey()); |
| assertEquals("value2", ev.getNewValue()); |
| } |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| reg2.localDestroy("key2"); |
| |
| reg2.localDestroyRegion(); |
| } |
| |
| @Test |
| public void testTxEvent() throws CacheException { |
| TransactionId myTxId; |
| Region<String, String> reg1 = this.region; |
| |
| this.txMgr.setListener(new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| listenerAfterCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| listenerAfterFailedCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| listenerAfterRollback = 1; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| listenerClose = 1; |
| } |
| }); |
| |
| // make sure each operation has the correct transaction event |
| // check create |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value1"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check put of existing entry |
| reg1.create("key1", "value0"); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = TxEventTestUtil.getPutEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check put of non-existent entry |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value0"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value0", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check d invalidate of existing entry |
| reg1.create("key1", "value0"); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.invalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getInvalidateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check l invalidate of existing entry |
| reg1.create("key1", "value0"); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localInvalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getInvalidateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| if (!isPR()) |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check d destroy of existing entry |
| reg1.create("key1", "value0"); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.destroy("key1"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check l destroy of existing entry |
| reg1.create("key1", "value0"); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localDestroy("key1"); |
| this.txMgr.rollback(); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| { |
| Cache teCache = this.te.getCache(); |
| assertEquals(teCache, this.cache); |
| List<EntryEvent<?, ?>> creates = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, creates.size()); |
| |
| for (EntryEvent ev : creates) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| if (!isPR()) |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| } |
| |
| private static class CountingCallBackValidator { |
| List<Object> asserts; |
| final String createWriterAssert = "create writer Assert"; |
| final String createListenerAssert = "create listener Assert"; |
| final String updateWriterAssert = "update writer Assert"; |
| final String updateListenerAssert = "update listener Assert"; |
| final String invalAssert = "invalidate Assert"; |
| final String destroyWriterAssert = "destroy writer Assert"; |
| final String destroyListenerAssert = "destroy listener Assert"; |
| final String localDestroyWriterAssert = "local destroy writer Assert"; |
| final String localDestroyListenerAssert = "local destroy listener Assert"; |
| |
| CountingCacheListener cl; |
| CountingCacheWriter cw; |
| |
| CountingCallBackValidator(CountingCacheListener cl, CountingCacheWriter cw) { |
| this.cl = cl; |
| this.cw = cw; |
| this.asserts = new ArrayList<>(8); |
| } |
| |
| void assertCreateWriterCnt(int cnt) { |
| assertCreateWriterCnt(cnt, true); |
| } |
| |
| void assertCreateWriterCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(createWriterAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cw.getBeforeCreateCalls()); |
| } |
| |
| void assertCreateListenerCnt(int cnt) { |
| assertCreateListenerCnt(cnt, true); |
| } |
| |
| void assertCreateListenerCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(createListenerAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cl.getAfterCreateCalls()); |
| } |
| |
| void assertDestroyWriterCnt(int cnt) { |
| assertDestroyWriterCnt(cnt, true); |
| } |
| |
| void assertDestroyWriterCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(destroyWriterAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cw.getBeforeDestroyCalls(false)); |
| } |
| |
| void assertDestroyListenerCnt(int cnt) { |
| assertDestroyListenerCnt(cnt, true); |
| } |
| |
| void assertDestroyListenerCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(destroyListenerAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cl.getAfterDestroyCalls(false)); |
| } |
| |
| void assertLocalDestroyWriterCnt(int cnt) { |
| assertLocalDestroyWriterCnt(cnt, true); |
| } |
| |
| void assertLocalDestroyWriterCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(localDestroyWriterAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(0, this.cw.getBeforeDestroyCalls(true)); |
| } |
| |
| void assertLocalDestroyListenerCnt(int cnt) { |
| assertLocalDestroyListenerCnt(cnt, true); |
| } |
| |
| void assertLocalDestroyListenerCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(localDestroyListenerAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cl.getAfterDestroyCalls(true)); |
| } |
| |
| void assertUpdateWriterCnt(int cnt) { |
| assertUpdateWriterCnt(cnt, true); |
| } |
| |
| void assertUpdateWriterCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(updateWriterAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cw.getBeforeUpdateCalls()); |
| } |
| |
| void assertUpdateListenerCnt(int cnt) { |
| assertUpdateListenerCnt(cnt, true); |
| } |
| |
| void assertUpdateListenerCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(updateListenerAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cl.getAfterUpdateCalls()); |
| } |
| |
| void assertInvalidateCnt(int cnt) { |
| assertInvalidateCnt(cnt, true); |
| } |
| |
| void assertInvalidateCnt(int cnt, boolean remember) { |
| if (remember) { |
| this.asserts.add(invalAssert); |
| this.asserts.add(cnt); |
| } |
| assertEquals(cnt, this.cl.getAfterInvalidateCalls()); |
| } |
| |
| void reAssert() { |
| Iterator assertItr = this.asserts.iterator(); |
| String assertType; |
| Integer count; |
| int cnt; |
| while (assertItr.hasNext()) { |
| assertType = (String) assertItr.next(); |
| assertTrue("CountingCallBackValidator reassert, did not have an associated count", |
| assertItr.hasNext()); |
| count = (Integer) assertItr.next(); |
| cnt = count; |
| if (assertType.equals(createWriterAssert)) { |
| this.assertCreateWriterCnt(cnt, false); |
| } else if (assertType.equals(createListenerAssert)) { |
| this.assertCreateListenerCnt(cnt, false); |
| } else if (assertType.equals(updateWriterAssert)) { |
| this.assertUpdateWriterCnt(cnt, false); |
| } else if (assertType.equals(updateListenerAssert)) { |
| this.assertUpdateListenerCnt(cnt, false); |
| } else if (assertType.equals(invalAssert)) { |
| this.assertInvalidateCnt(cnt, false); |
| } else if (assertType.equals(destroyWriterAssert)) { |
| this.assertDestroyWriterCnt(cnt, false); |
| } else if (assertType.equals(destroyListenerAssert)) { |
| this.assertDestroyListenerCnt(cnt, false); |
| } else if (assertType.equals(localDestroyWriterAssert)) { |
| this.assertLocalDestroyWriterCnt(cnt, false); |
| } else if (assertType.equals(localDestroyListenerAssert)) { |
| this.assertLocalDestroyListenerCnt(cnt, false); |
| } else { |
| fail("CountingCallBackValidator reassert, unknown type"); |
| } |
| } |
| } |
| |
| void reset() { |
| this.cl.reset(); |
| this.cw.reset(); |
| this.asserts.clear(); |
| } |
| } |
| |
| private interface CountingCacheListener extends CacheListener { |
| int getAfterCreateCalls(); |
| |
| int getAfterUpdateCalls(); |
| |
| int getAfterInvalidateCalls(); |
| |
| int getAfterDestroyCalls(boolean fetchLocal); |
| |
| void reset(); |
| } |
| |
| private interface CountingCacheWriter extends CacheWriter { |
| int getBeforeCreateCalls(); |
| |
| int getBeforeUpdateCalls(); |
| |
| int getBeforeDestroyCalls(boolean fetchLocal); |
| |
| void reset(); |
| } |
| |
| @Test |
| public void testTxAlgebra() throws CacheException { |
| TransactionId myTxId; |
| Region<String, String> reg1 = this.region; |
| |
| this.txMgr.setListener(new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| listenerAfterCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| listenerAfterFailedCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| listenerAfterRollback = 1; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| listenerClose = 1; |
| } |
| }); |
| AttributesMutator<String, String> mutator = this.region.getAttributesMutator(); |
| CountingCacheListener cntListener = new CountingCacheListener() { |
| volatile int aCreateCalls, aUpdateCalls, aInvalidateCalls, aDestroyCalls, aLocalDestroyCalls; |
| |
| @Override |
| public void close() {} |
| |
| @Override |
| public void reset() { |
| this.aCreateCalls = this.aUpdateCalls = |
| this.aInvalidateCalls = this.aDestroyCalls = this.aLocalDestroyCalls = 0; |
| } |
| |
| @Override |
| public void afterCreate(EntryEvent e) { |
| ++this.aCreateCalls; |
| } |
| |
| @Override |
| public void afterUpdate(EntryEvent e) { |
| ++this.aUpdateCalls; |
| } |
| |
| @Override |
| public void afterInvalidate(EntryEvent e) { |
| ++this.aInvalidateCalls; |
| } |
| |
| @Override |
| public void afterDestroy(EntryEvent e) { |
| if (e.getOperation().isDistributed()) { |
| ++this.aDestroyCalls; |
| } else { |
| ++this.aLocalDestroyCalls; |
| } |
| } |
| |
| @Override |
| public void afterRegionInvalidate(RegionEvent e) { |
| fail("Unexpected afterRegionInvalidate in testTxAlgebra"); |
| } |
| |
| @Override |
| public void afterRegionDestroy(RegionEvent e) { |
| if (!e.getOperation().isClose()) { |
| fail("Unexpected afterRegionDestroy in testTxAlgebra"); |
| } |
| } |
| |
| @Override |
| public void afterRegionClear(RegionEvent event) {} |
| |
| @Override |
| public void afterRegionCreate(RegionEvent event) {} |
| |
| @Override |
| public void afterRegionLive(RegionEvent event) {} |
| |
| @Override |
| public int getAfterCreateCalls() { |
| return this.aCreateCalls; |
| } |
| |
| @Override |
| public int getAfterUpdateCalls() { |
| return this.aUpdateCalls; |
| } |
| |
| @Override |
| public int getAfterInvalidateCalls() { |
| return this.aInvalidateCalls; |
| } |
| |
| @Override |
| public int getAfterDestroyCalls(boolean fetchLocal) { |
| return fetchLocal ? this.aLocalDestroyCalls : this.aDestroyCalls; |
| } |
| }; |
| mutator.addCacheListener(cntListener); |
| CountingCacheWriter cntWriter = new CountingCacheWriter() { |
| int bCreateCalls, bUpdateCalls, bDestroyCalls, bLocalDestroyCalls; |
| |
| @Override |
| public void close() {} |
| |
| @Override |
| public void reset() { |
| this.bCreateCalls = this.bUpdateCalls = this.bDestroyCalls = this.bLocalDestroyCalls = 0; |
| } |
| |
| @Override |
| public void beforeCreate(EntryEvent e) { |
| ++this.bCreateCalls; |
| } |
| |
| @Override |
| public void beforeUpdate(EntryEvent e) { |
| ++this.bUpdateCalls; |
| } |
| |
| @Override |
| public void beforeDestroy(EntryEvent e) { |
| ++this.bDestroyCalls; |
| } |
| |
| @Override |
| public void beforeRegionDestroy(RegionEvent e) { |
| fail("Unexpected beforeRegionDestroy in testTxAlgebra"); |
| } |
| |
| @Override |
| public void beforeRegionClear(RegionEvent e) { |
| fail("Unexpected beforeRegionClear in testTxAlgebra"); |
| } |
| |
| @Override |
| public int getBeforeCreateCalls() { |
| return this.bCreateCalls; |
| } |
| |
| @Override |
| public int getBeforeUpdateCalls() { |
| return this.bUpdateCalls; |
| } |
| |
| @Override |
| public int getBeforeDestroyCalls(boolean fetchLocal) { |
| return fetchLocal ? this.bLocalDestroyCalls : this.bDestroyCalls; |
| } |
| }; |
| mutator.setCacheWriter(cntWriter); |
| |
| CountingCallBackValidator callbackVal = new CountingCallBackValidator(cntListener, cntWriter); |
| |
| // make sure each op sequence has the correct affect transaction event |
| // check C + C -> EX |
| // check C + P -> C |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| try { |
| reg1.create("key1", "value2"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| callbackVal.assertCreateWriterCnt(1, /* remember */ false); |
| reg1.put("key1", "value2"); |
| callbackVal.assertUpdateWriterCnt(1); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| // Make sure listener callbacks were not triggered before commit |
| callbackVal.assertCreateListenerCnt(0, false); |
| callbackVal.assertUpdateListenerCnt(0); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value2", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // Check C + DI -> C |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| callbackVal.assertCreateListenerCnt(0, false); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| assertEquals(1, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // TODO: mitch implement the following |
| // check LI + DI -> NOOP |
| // check DI + LI -> NOOP |
| // check DI + DI -> NOOP |
| // check LI + LI -> NOOP |
| |
| // check C + DD -> NOOP |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| reg1.create("key1", "value0"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| callbackVal.assertDestroyListenerCnt(0); |
| this.txMgr.commit(); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, this.te.getEvents().size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| |
| // Check C + LI -> C |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // Check C + LI + C -> EX |
| // Check C + LI + P -> C |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| try { |
| reg1.create("key1", "ex"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| callbackVal.assertCreateWriterCnt(1, /* remember */ false); |
| reg1.put("key1", "value2"); |
| callbackVal.assertUpdateWriterCnt(1); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0, false); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value2", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // Check C + LI + LD -> NOOP |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, this.te.getEvents().size()); |
| |
| // Check C + LI + DD -> NOOP |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, this.te.getEvents().size()); |
| |
| // check C + LD -> NOOP |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| reg1.create("key1", "value0"); |
| callbackVal.assertCreateWriterCnt(1); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, this.te.getEvents().size()); |
| |
| // check C + LD + D -> EX |
| // check C + LD + I -> EX |
| // check C + LD + C -> C |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value0"); |
| callbackVal.assertCreateWriterCnt(1, /* remember */ false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| try { |
| reg1.localDestroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertLocalDestroyWriterCnt(1, /* remember */ false); |
| try { |
| reg1.destroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertDestroyWriterCnt(0); |
| try { |
| reg1.localInvalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0); |
| try { |
| reg1.invalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0, /* remember */ false); |
| reg1.create("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(2); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check C + LD + P -> C |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.create("key1", "value0"); |
| callbackVal.assertCreateWriterCnt(1, /* remember */ false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| reg1.put("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(2); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(1); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check put of existing entry |
| // check P + C -> EX |
| // check P + P -> P |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1, /* remember */ false); |
| try { |
| reg1.create("key1", "value2"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| callbackVal.assertUpdateWriterCnt(1, /* remember */ false); |
| callbackVal.assertCreateWriterCnt(0); |
| reg1.put("key1", "value3"); |
| callbackVal.assertUpdateWriterCnt(2); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = TxEventTestUtil.getPutEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check P + DI -> DI |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(1); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.reAssert(); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getInvalidateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check P + DD -> D |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check P + LI -> LI |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| assertTrue(reg1.containsKey("key1")); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals(null, reg1.getEntry("key1").getValue()); |
| assertTrue(!reg1.containsValueForKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getInvalidateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // Check P + LI + C -> EX |
| // Check P + LI + P -> P |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1, /* remember */ false); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| try { |
| reg1.create("key1", "ex"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| callbackVal.assertCreateWriterCnt(0); |
| callbackVal.assertUpdateWriterCnt(1, /* remember */ false); |
| reg1.put("key1", "value2"); |
| callbackVal.assertUpdateWriterCnt(2); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = TxEventTestUtil.getPutEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value2", ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // Check P + LI + LD -> LD |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // Check P + LI + DD -> DD |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.assertDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check P + LD -> LD |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check P + LD + D -> EX |
| // check P + LD + I -> EX |
| // check P + LD + C -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| try { |
| reg1.localDestroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertLocalDestroyWriterCnt(1, /* remember */ false); |
| try { |
| reg1.destroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertDestroyWriterCnt(0); |
| try { |
| reg1.localInvalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0, /* remember */ false); |
| try { |
| reg1.invalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0); |
| reg1.create("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check P + LD + P -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1, /* remember */ false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| reg1.put("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check DI + C -> EX |
| // check DI + P -> P |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| try { |
| reg1.create("key1", "value1"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| callbackVal.assertCreateWriterCnt(0); |
| reg1.put("key1", "value2"); |
| callbackVal.assertUpdateWriterCnt(1); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = TxEventTestUtil.getPutEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value2", ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check DI + DD -> D |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check DI + LD -> LD |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check DI + LD + D -> EX |
| // check DI + LD + I -> EX |
| // check DI + LD + C -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| try { |
| reg1.localDestroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertLocalDestroyWriterCnt(1, /* remember */ false); |
| try { |
| reg1.destroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertDestroyWriterCnt(0); |
| try { |
| reg1.localInvalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0, /* remember */ false); |
| try { |
| reg1.invalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0, /* remember */ false); |
| reg1.create("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check DI + LD + P -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.invalidate("key1", "value1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| reg1.put("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check LI + C -> EX |
| // check LI + P -> P |
| reg1.create("key1", "value0"); |
| this.txMgr.begin(); |
| callbackVal.reset(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| try { |
| reg1.create("key1", "value1"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| callbackVal.assertCreateWriterCnt(0); |
| reg1.put("key1", "value2"); |
| callbackVal.assertUpdateWriterCnt(1); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.reAssert(); |
| assertEquals("value2", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = TxEventTestUtil.getPutEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value2", ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check LI + DD -> DD |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check LI + LD -> LD |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(1); |
| callbackVal.reAssert(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getDestroyEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals(null, ev.getNewValue()); |
| assertEquals("value0", ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check LI + LD + D -> EX |
| // check LI + LD + I -> EX |
| // check LI + LD + C -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| assertTrue(!reg1.containsKey("key1")); |
| try { |
| reg1.localDestroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertLocalDestroyWriterCnt(1, /* remember */ false); |
| try { |
| reg1.destroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertDestroyWriterCnt(0); |
| try { |
| reg1.localInvalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0, /* remember */ false); |
| try { |
| reg1.invalidate("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException ok) { |
| } |
| callbackVal.assertInvalidateCnt(0, /* remember */ false); |
| reg1.create("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check LI + LD + P -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localInvalidate("key1", "value1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| reg1.put("key1", "value3"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value3", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value3", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check init state LI + P + I -> I token (bug 33073) |
| reg1.create("key1", "value0"); |
| reg1.localInvalidate("key1"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| reg1.invalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| this.txMgr.commit(); |
| callbackVal.assertUpdateListenerCnt(0); |
| callbackVal.assertInvalidateCnt(1); |
| callbackVal.reAssert(); |
| assertNull(reg1.getEntry("key1").getValue()); |
| { |
| // Special check to assert Invaldate token |
| NonTXEntry nonTXe = (NonTXEntry) reg1.getEntry("key1"); |
| assertTrue(nonTXe.getRegionEntry().isInvalid()); |
| } |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getInvalidateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertNull(ev.getNewValue()); |
| assertNull(ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| |
| // check init state I + P + LI -> LI token (bug 33073) |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.put("key1", "value1"); |
| callbackVal.assertUpdateWriterCnt(1); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| reg1.localInvalidate("key1"); |
| callbackVal.assertInvalidateCnt(0, false); |
| this.txMgr.commit(); |
| callbackVal.assertInvalidateCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.reAssert(); |
| assertNull(reg1.getEntry("key1").getValue()); |
| { |
| // Special check to assert Local Invaldate token |
| NonTXEntry nonTXe = (NonTXEntry) reg1.getEntry("key1"); |
| assertTrue(nonTXe.getRegionEntry().isInvalid()); |
| } |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getInvalidateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertNull(ev.getNewValue()); |
| assertNull(ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(!ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check DD + C -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check DD + P -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.destroy("key1"); |
| callbackVal.assertDestroyWriterCnt(1); |
| reg1.put("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check LD + C -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| reg1.create("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| |
| // check LD + P -> C |
| reg1.create("key1", "value0"); |
| callbackVal.reset(); |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| reg1.localDestroy("key1"); |
| callbackVal.assertLocalDestroyWriterCnt(1); |
| reg1.put("key1", "value1"); |
| callbackVal.assertCreateWriterCnt(1); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| callbackVal.assertLocalDestroyListenerCnt(0); |
| callbackVal.assertCreateListenerCnt(0); |
| callbackVal.assertUpdateListenerCnt(1); |
| callbackVal.reAssert(); |
| assertEquals("value1", reg1.getEntry("key1").getValue()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(1, this.te.getEvents().size()); |
| { |
| List<EntryEvent<?, ?>> events = |
| TxEventTestUtil.getCreateEvents(this.te.getEvents()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| assertEquals(1, events.size()); |
| |
| for (EntryEvent ev : events) { |
| assertEquals(myTxId, ev.getTransactionId()); |
| assertTrue(ev.getRegion() == reg1); |
| assertEquals("key1", ev.getKey()); |
| assertEquals("value1", ev.getNewValue()); |
| assertEquals(null, ev.getOldValue()); |
| verifyEventProps(ev); |
| assertEquals(null, ev.getCallbackArgument()); |
| assertEquals(true, ev.isCallbackArgumentAvailable()); |
| assertTrue(!ev.isOriginRemote()); |
| assertTrue(!ev.getOperation().isExpiration()); |
| assertTrue(ev.getOperation().isDistributed()); |
| } |
| } |
| reg1.localDestroy("key1"); |
| } |
| |
| private void doNonTxInvalidateRegionOp(CachePerfStats stats) throws Exception { |
| int txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.region.create("key2", "value2"); |
| this.txMgr.begin(); |
| try { |
| this.region.localInvalidateRegion(); |
| fail("Should have gotten an UnsupportedOperationInTransactionException"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // this is expected |
| } |
| this.txMgr.rollback(); |
| assertEquals("value1", this.region.get("key1")); |
| assertEquals("value2", this.region.get("key2")); |
| assertEquals(txRollbackChanges, stats.getTxRollbackChanges()); |
| |
| this.region.put("key1", "value1"); |
| this.region.put("key2", "value2"); |
| this.txMgr.begin(); |
| try { |
| this.region.invalidateRegion(); |
| fail("Should have gotten an UnsupportedOperationInTransactionException"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // this is expected |
| } |
| this.txMgr.rollback(); |
| assertEquals("value1", this.region.get("key1")); |
| assertEquals("value2", this.region.get("key2")); |
| assertEquals(txRollbackChanges, stats.getTxRollbackChanges()); |
| |
| } |
| |
| private void doNonTxDestroyRegionOp(CachePerfStats stats) throws Exception { |
| int txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.put("key1", "value1"); |
| this.region.put("key2", "value2"); |
| this.txMgr.begin(); |
| try { |
| this.region.localDestroyRegion(); |
| fail("Should have gotten an UnsupportedOperationInTransactionException"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // this is expected |
| } |
| this.txMgr.rollback(); |
| assertTrue(!this.region.isDestroyed()); |
| assertEquals(txRollbackChanges, stats.getTxRollbackChanges()); |
| |
| this.txMgr.begin(); |
| try { |
| this.region.destroyRegion(); |
| fail("Should have gotten an UnsupportedOperationInTransactionException"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // this is expected |
| } |
| this.txMgr.rollback(); |
| assertTrue(!this.region.isDestroyed()); |
| assertEquals(txRollbackChanges, stats.getTxRollbackChanges()); |
| } |
| |
| @Test |
| public void testNonTxRegionOps() throws Exception { |
| final CachePerfStats stats = this.cache.getCachePerfStats(); |
| doNonTxInvalidateRegionOp(stats); |
| doNonTxDestroyRegionOp(stats); |
| } |
| |
| @Test |
| public void testEntryNotFound() { |
| // make sure operations that should fail with EntryNotFoundException |
| // do so when done transactionally |
| try { |
| try { |
| this.region.destroy("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| try { |
| this.region.localDestroy("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| try { |
| this.region.invalidate("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| try { |
| this.region.localInvalidate("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| |
| this.txMgr.begin(); |
| try { |
| this.region.destroy("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| this.txMgr.rollback(); |
| this.txMgr.begin(); |
| try { |
| this.region.localDestroy("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| this.txMgr.rollback(); |
| this.txMgr.begin(); |
| try { |
| this.region.invalidate("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| this.txMgr.rollback(); |
| this.txMgr.begin(); |
| try { |
| this.region.localInvalidate("noEntry"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| this.txMgr.rollback(); |
| |
| // check to see if EntryExistsException works in transactions |
| this.region.create("key1", "value1"); |
| try { |
| this.region.create("key1", "value2"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException expected) { |
| } |
| this.txMgr.begin(); |
| try { |
| this.region.create("key1", "value2"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException expected) { |
| } |
| this.txMgr.rollback(); |
| } catch (CacheException ex) { |
| fail("unexpected " + ex); |
| } |
| } |
| |
| @Test |
| public void testListener() { |
| assertTrue(this.txMgr.getListener() == null); |
| TransactionListener oldListener = this.txMgr.setListener(new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| listenerAfterCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| listenerAfterFailedCommit = 1; |
| te = event; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| listenerAfterRollback = 1; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| listenerClose = 1; |
| } |
| }); |
| assertTrue(oldListener == null); |
| this.txMgr.begin(); |
| TransactionId myTxId = this.txMgr.getTransactionId(); |
| assertEquals(0, this.listenerAfterRollback); |
| this.txMgr.rollback(); |
| assertEquals(1, this.listenerAfterRollback); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, this.te.getEvents().size()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| |
| this.txMgr.begin(); |
| myTxId = this.txMgr.getTransactionId(); |
| try { |
| assertEquals(0, this.listenerAfterCommit); |
| this.txMgr.commit(); |
| } catch (CommitConflictException unexpected) { |
| fail("did not expect " + unexpected); |
| } |
| assertEquals(1, this.listenerAfterCommit); |
| assertEquals(0, TxEventTestUtil.getCreateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getPutEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getInvalidateEvents(this.te.getEvents()).size()); |
| assertEquals(0, TxEventTestUtil.getDestroyEvents(this.te.getEvents()).size()); |
| assertEquals(0, this.te.getEvents().size()); |
| assertEquals(myTxId, this.te.getTransactionId()); |
| |
| assertEquals(0, this.listenerClose); |
| oldListener = this.txMgr.setListener(new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| listenerAfterCommit = 2; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| listenerAfterFailedCommit = 2; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| listenerAfterRollback = 2; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| listenerClose = 2; |
| } |
| }); |
| assertEquals(1, this.listenerClose); |
| |
| this.txMgr.begin(); |
| assertEquals(1, this.listenerAfterRollback); |
| this.txMgr.rollback(); |
| assertEquals(2, this.listenerAfterRollback); |
| this.txMgr.begin(); |
| this.txMgr.setListener(oldListener); |
| assertEquals(2, this.listenerClose); |
| this.txMgr.rollback(); |
| assertEquals(1, this.listenerAfterRollback); |
| |
| closeCache(); |
| assertEquals(1, this.listenerClose); |
| } |
| |
| // make sure standard Cache(Listener,Writer) |
| // are not called during rollback |
| @Test |
| public void testNoCallbacksOnRollback() throws CacheException { |
| // install listeners |
| AttributesMutator<String, String> mutator = this.region.getAttributesMutator(); |
| mutator.addCacheListener(new CacheListenerAdapter<String, String>() { |
| @Override |
| public void close() { |
| cbCount++; |
| } |
| |
| @Override |
| public void afterCreate(EntryEvent event) { |
| cbCount++; |
| } |
| |
| @Override |
| public void afterUpdate(EntryEvent event) { |
| cbCount++; |
| } |
| |
| @Override |
| public void afterInvalidate(EntryEvent event) { |
| cbCount++; |
| } |
| |
| @Override |
| public void afterDestroy(EntryEvent event) { |
| cbCount++; |
| } |
| |
| @Override |
| public void afterRegionInvalidate(RegionEvent event) { |
| cbCount++; |
| } |
| |
| @Override |
| public void afterRegionDestroy(RegionEvent event) { |
| cbCount++; |
| } |
| }); |
| mutator.setCacheWriter(new CacheWriter<String, String>() { |
| @Override |
| public void close() { |
| cbCount++; |
| } |
| |
| @Override |
| public void beforeUpdate(EntryEvent event) throws CacheWriterException { |
| cbCount++; |
| } |
| |
| @Override |
| public void beforeCreate(EntryEvent event) throws CacheWriterException { |
| cbCount++; |
| } |
| |
| @Override |
| public void beforeDestroy(EntryEvent event) throws CacheWriterException { |
| cbCount++; |
| } |
| |
| @Override |
| public void beforeRegionDestroy(RegionEvent event) throws CacheWriterException { |
| cbCount++; |
| } |
| |
| @Override |
| public void beforeRegionClear(RegionEvent event) throws CacheWriterException { |
| cbCount++; |
| } |
| }); |
| |
| this.txMgr.begin(); |
| this.region.create("key1", "value1"); |
| this.cbCount = 0; |
| this.txMgr.rollback(); |
| assertEquals(0, this.cbCount); |
| |
| this.cbCount = 0; |
| this.region.create("key1", "value1"); |
| // do a santify check to make sure callbacks are installed |
| assertEquals(2, this.cbCount); // 2 -> 1writer + 1listener |
| |
| this.txMgr.begin(); |
| this.region.put("key1", "value2"); |
| this.cbCount = 0; |
| this.txMgr.rollback(); |
| assertEquals(0, this.cbCount); |
| this.region.localDestroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.localDestroy("key1"); |
| this.cbCount = 0; |
| this.txMgr.rollback(); |
| assertEquals(0, this.cbCount); |
| |
| this.region.put("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.destroy("key1"); |
| this.cbCount = 0; |
| this.txMgr.rollback(); |
| assertEquals(0, this.cbCount); |
| |
| this.region.put("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.localInvalidate("key1"); |
| this.cbCount = 0; |
| this.txMgr.rollback(); |
| assertEquals(0, this.cbCount); |
| this.region.localDestroy("key1"); |
| |
| this.region.put("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.cbCount = 0; |
| this.txMgr.rollback(); |
| assertEquals(0, this.cbCount); |
| |
| this.region.localDestroy("key1"); |
| } |
| |
| /** |
| * TXCallBackValidator is a container for holding state for validating Cache callbacks |
| */ |
| private class TXCallBackValidator { |
| boolean passedValidation; |
| boolean suspendValidation; |
| int expectedCallCount; |
| Object key; |
| Object oldVal; |
| boolean oldValIdentCheck; |
| Object newVal; |
| boolean newValIdentCheck; |
| TransactionId txId; |
| boolean isDistributed; |
| boolean isLocalLoad; |
| boolean isCreate; |
| boolean isUpdate; |
| boolean isDestroyed; |
| boolean isInvalidate; |
| Object callBackArg; |
| |
| /** |
| * EntryEvent, CallCount validator for callbacks (CacheWriter, CacheListener |
| */ |
| boolean validate(EntryEvent event, int cnt) { |
| if (this.isSuspendValidation()) { |
| return true; |
| } |
| this.passedValidation = false; |
| assertEquals("Expected Call Count Assertion!", this.expectedCallCount, cnt); |
| |
| assertTrue(!event.getOperation().isExpiration()); |
| assertTrue(!event.getOperation().isNetLoad()); |
| assertEquals("isLoad Assertion!", this.isLoad(), event.getOperation().isLoad()); |
| assertEquals("isLocalLoad Assertion!", this.isLoad(), event.getOperation().isLocalLoad()); |
| assertTrue(!event.getOperation().isNetSearch()); |
| assertTrue(!event.isOriginRemote()); |
| assertNotNull(event.getRegion()); |
| assertNotNull(event.getRegion().getCache()); |
| assertNotNull(event.getRegion().getCache().getCacheTransactionManager()); |
| assertEquals(this.getTXId(), event.getTransactionId()); |
| |
| if (!isPR()) |
| assertEquals("IsDistributed Assertion!", this.isDistributed(), |
| event.getOperation().isDistributed()); |
| assertEquals(this.getKey(), event.getKey()); |
| assertSame(this.getCallBackArg(), event.getCallbackArgument()); |
| if (newValIdentCheck) { |
| assertSame(newVal, event.getNewValue()); |
| } else { |
| assertEquals(newVal, event.getNewValue()); |
| } |
| if (oldValIdentCheck) { |
| assertSame(oldVal, event.getOldValue()); |
| } else { |
| assertEquals(oldVal, event.getOldValue()); |
| } |
| this.passedValidation = true; |
| return true; |
| } |
| |
| int setExpectedCount(int newVal) { |
| int oldVal = this.expectedCallCount; |
| this.expectedCallCount = newVal; |
| return oldVal; |
| } |
| |
| void setKey(Object key) { |
| this.key = key; |
| } |
| |
| Object getKey() { |
| return this.key; |
| } |
| |
| void setOldValue(Object val, boolean checkWithIdentity) { |
| this.oldVal = val; |
| this.oldValIdentCheck = checkWithIdentity; |
| } |
| |
| Object getOldValue() { |
| return this.oldVal; |
| } |
| |
| void setNewValue(Object val, boolean checkWithIdentity) { |
| this.newVal = val; |
| this.newValIdentCheck = checkWithIdentity; |
| } |
| |
| Object getNewValue() { |
| return this.newVal; |
| } |
| |
| TransactionId setTXId(TransactionId txId) { |
| TransactionId old = this.txId; |
| this.txId = txId; |
| return old; |
| } |
| |
| TransactionId getTXId() { |
| return this.txId; |
| } |
| |
| void setIsDistributed(boolean isDistributed) { |
| this.isDistributed = isDistributed; |
| } |
| |
| Object getCallBackArg() { |
| return this.callBackArg; |
| } |
| |
| void setCallBackArg(Object callBackArg) { |
| this.callBackArg = callBackArg; |
| } |
| |
| boolean isDistributed() { |
| return this.isDistributed; |
| } |
| |
| void setIsCreate(boolean isCreate) { |
| this.isCreate = isCreate; |
| } |
| |
| boolean isCreate() { |
| return this.isCreate; |
| } |
| |
| void setIsUpdate(boolean isUpdate) { |
| this.isUpdate = isUpdate; |
| } |
| |
| boolean isUpdate() { |
| return this.isUpdate; |
| } |
| |
| void setIsDestroy(boolean isDestroyed) { |
| this.isDestroyed = isDestroyed; |
| } |
| |
| boolean isDestroy() { |
| return this.isDestroyed; |
| } |
| |
| void setIsInvalidate(boolean isInvalidate) { |
| this.isInvalidate = isInvalidate; |
| } |
| |
| boolean isInvalidate() { |
| return this.isInvalidate; |
| } |
| |
| void setIsLoad(boolean isLoad) { |
| this.isLocalLoad = isLoad; |
| } |
| |
| boolean isLoad() { |
| return this.isLocalLoad; |
| } |
| |
| boolean suspendValidation(boolean toggle) { |
| boolean oldVal = this.suspendValidation; |
| this.suspendValidation = toggle; |
| return oldVal; |
| } |
| |
| boolean isSuspendValidation() { |
| return this.suspendValidation; |
| } |
| |
| void setPassedValidation(boolean passedValidation) { |
| this.passedValidation = passedValidation; |
| } |
| |
| boolean passedValidation() { |
| return this.passedValidation; |
| } |
| } |
| |
| private interface ValidatableCacheListener extends CacheListener { |
| void setValidator(TXCallBackValidator v); |
| |
| void validate(); |
| |
| void validateNoEvents(); |
| |
| void reset(); |
| |
| void setExpectedCount(int count); |
| |
| int getCallCount(); |
| } |
| |
| private interface ValidatableCacheWriter extends CacheWriter { |
| void setValidator(TXCallBackValidator v); |
| |
| int getCallCount(); |
| |
| void localDestroyMakeup(int count); |
| |
| void validate(); |
| |
| void reset(); |
| |
| void validateNoEvents(); |
| } |
| |
| /** |
| * Test to make sure CacheListener callbacks are called in place with the CacheEvents properly |
| * constructed |
| */ |
| @Test |
| public void testCacheCallbacks() throws CacheException { |
| final String key1 = "Key1"; |
| final String value1 = "value1"; |
| final String value2 = "value2"; |
| final String callBackArg = "call back arg"; |
| // install listeners |
| AttributesMutator<String, String> mutator = this.region.getAttributesMutator(); |
| |
| TXCallBackValidator cbv = new TXCallBackValidator(); |
| |
| // Cache Listener |
| ValidatableCacheListener vCl = new ValidatableCacheListener() { |
| TXCallBackValidator v; |
| int callCount; |
| int prevCallCount; |
| EntryEvent lastEvent; |
| |
| @Override |
| public void validate() { |
| this.v.validate(this.lastEvent, this.callCount); |
| } |
| |
| void validate(EntryEvent event) { |
| this.v.validate(event, ++this.callCount); |
| } |
| |
| @Override |
| public void setValidator(TXCallBackValidator v) { |
| this.v = v; |
| } |
| |
| @Override |
| public void close() {} |
| |
| @Override |
| public void afterCreate(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| this.validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsCreate Assertion!", this.v.isCreate()); |
| assertTrue(event.getRegion().containsKey(this.v.getKey())); |
| assertTrue(event.getRegion().containsValueForKey(this.v.getKey())); |
| assertNotNull(event.getRegion().getEntry(event.getKey()).getValue()); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void afterUpdate(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsUpdate Assertion!", this.v.isUpdate()); |
| assertTrue(event.getRegion().containsKey(this.v.getKey())); |
| assertTrue(event.getRegion().containsValueForKey(this.v.getKey())); |
| assertNotNull(event.getRegion().getEntry(event.getKey()).getValue()); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void afterInvalidate(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsInvalidate Assertion!", this.v.isInvalidate()); |
| assertTrue(event.getRegion().containsKey(this.v.getKey())); |
| assertTrue(!event.getRegion().containsValueForKey(this.v.getKey())); |
| assertNull(event.getRegion().getEntry(event.getKey()).getValue()); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void afterDestroy(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsDestroy Assertion!", this.v.isDestroy()); |
| assertTrue(!event.getRegion().containsKey(this.v.getKey())); |
| assertTrue(!event.getRegion().containsValueForKey(this.v.getKey())); |
| assertNull(event.getRegion().getEntry(event.getKey())); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void afterRegionInvalidate(RegionEvent event) { |
| fail("Unexpected invocation of afterRegionInvalidate"); |
| } |
| |
| @Override |
| public void afterRegionDestroy(RegionEvent event) { |
| if (!event.getOperation().isClose()) { |
| fail("Unexpected invocation of afterRegionDestroy"); |
| } |
| } |
| |
| @Override |
| public void afterRegionClear(RegionEvent event) {} |
| |
| @Override |
| public void afterRegionCreate(RegionEvent event) {} |
| |
| @Override |
| public void afterRegionLive(RegionEvent event) {} |
| |
| @Override |
| public void reset() { |
| lastEvent = null; |
| prevCallCount = callCount; |
| } |
| |
| @Override |
| public void validateNoEvents() { |
| assertNull("Did not expect listener callback", lastEvent); |
| assertEquals(prevCallCount, callCount); |
| } |
| |
| @Override |
| public void setExpectedCount(int count) { |
| callCount = count; |
| } |
| |
| @Override |
| public int getCallCount() { |
| return callCount; |
| } |
| }; |
| |
| vCl.setValidator(cbv); |
| mutator.addCacheListener(vCl); |
| |
| // CacheWriter |
| ValidatableCacheWriter vCw = new ValidatableCacheWriter() { |
| TXCallBackValidator v; |
| int callCount; |
| int prevCallCount; |
| EntryEvent lastEvent; |
| |
| @Override |
| public int getCallCount() { |
| return this.callCount; |
| } |
| |
| @Override |
| public void localDestroyMakeup(int count) { |
| this.callCount += count; |
| } |
| |
| @Override |
| public void validate() { |
| this.v.validate(this.lastEvent, this.callCount); |
| } |
| |
| void validate(EntryEvent event) { |
| this.v.validate(event, ++this.callCount); |
| } |
| |
| @Override |
| public void setValidator(TXCallBackValidator v) { |
| this.v = v; |
| } |
| |
| @Override |
| public void close() {} |
| |
| @Override |
| public void beforeCreate(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsCreate Assertion!", this.v.isCreate()); |
| assertTrue(!event.getRegion().containsKey(this.v.getKey())); |
| assertTrue(!event.getRegion().containsValueForKey(this.v.getKey())); |
| assertNull(event.getRegion().getEntry(event.getKey())); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void beforeUpdate(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsUpdate Assertion!", this.v.isUpdate()); |
| assertTrue(event.getRegion().containsKey(this.v.getKey())); |
| // Can not assert the following line, as the value being update may be invalid |
| // assertTrue(event.getRegion().containsValueForKey(this.v.getKey())); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void beforeDestroy(EntryEvent event) { |
| lastEvent = event; |
| if (this.v.isSuspendValidation()) { |
| return; |
| } |
| validate(event); |
| this.v.setPassedValidation(false); |
| assertTrue("IsDestroy Assertion!", this.v.isDestroy()); |
| assertTrue(event.getRegion().containsKey(this.v.getKey())); |
| this.v.setPassedValidation(true); |
| } |
| |
| @Override |
| public void beforeRegionDestroy(RegionEvent event) { |
| fail("Unexpected invocation of beforeRegionDestroy"); |
| } |
| |
| @Override |
| public void beforeRegionClear(RegionEvent event) { |
| fail("Unexpected invocation of beforeRegionClear"); |
| } |
| |
| @Override |
| public void reset() { |
| lastEvent = null; |
| prevCallCount = callCount; |
| } |
| |
| @Override |
| public void validateNoEvents() { |
| assertNull("Did not expect a writer event", lastEvent); |
| assertEquals(prevCallCount, callCount); |
| } |
| }; |
| vCw.setValidator(cbv); |
| mutator.setCacheWriter(vCw); |
| |
| // Cache Loader |
| mutator.setCacheLoader(new CacheLoader() { |
| int count = 0; |
| |
| @Override |
| public Object load(LoaderHelper helper) throws CacheLoaderException { |
| return count++; |
| } |
| |
| @Override |
| public void close() {} |
| }); |
| |
| // Use this to track the number of callout method invocations |
| int appCallCount = 1; |
| |
| // Create => beforeCreate/afterCreate tests |
| cbv.setKey(key1); |
| cbv.setCallBackArg(callBackArg); |
| cbv.setNewValue(value1, false); |
| cbv.setOldValue(null, true); |
| cbv.setIsDistributed(true); |
| cbv.setIsLoad(false); |
| cbv.setIsCreate(true); |
| cbv.setIsUpdate(false); |
| // Test non-transactional create expecting beforeCreate/afterCreate call |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.create(key1, value1, callBackArg); |
| assertTrue("Non-TX Create Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| cbv.suspendValidation(false); |
| // Test transactional create expecting afterCreate call |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.create(key1, value1, callBackArg); |
| this.txMgr.commit(); |
| assertTrue("TX Create Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| |
| // Put => afterCreate tests |
| cbv.suspendValidation(false); |
| cbv.setNewValue(value2, false); |
| cbv.setOldValue(null, true); |
| cbv.setIsDistributed(true); |
| cbv.setIsLoad(false); |
| cbv.setIsCreate(true); |
| cbv.setIsUpdate(false); |
| // Test non-transactional put expecting afterCreate call due to no |
| // previous Entry |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.put(key1, value2, callBackArg); |
| assertTrue("Non-TX Put->Create Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| cbv.suspendValidation(false); |
| // Test transactional put expecting afterCreate call due to no |
| // previous Entry |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.put(key1, value2, callBackArg); |
| this.txMgr.commit(); |
| assertTrue("TX Put->Create Validation Assertion", cbv.passedValidation()); |
| |
| // Put => afterUpdate tests |
| cbv.setNewValue(value1, false); |
| cbv.setOldValue(value2, false); |
| cbv.setIsDistributed(true); |
| cbv.setIsLoad(false); |
| cbv.setIsCreate(false); |
| cbv.setIsUpdate(true); |
| // Test non-transactional put expecting afterUpdate call due to |
| // previous Entry |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.put(key1, value1, callBackArg); |
| assertTrue("Non-TX Put->Update Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| this.region.put(key1, value2); |
| cbv.suspendValidation(false); |
| // Test transactional put expecting afterUpdate call due to |
| // previous Entry |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.put(key1, value1, callBackArg); |
| this.txMgr.commit(); |
| assertTrue("TX Put->Update Validation Assertion", cbv.passedValidation()); |
| |
| // LocalDestroy => afterDestroy, non-distributed tests |
| cbv.setNewValue(null, true); |
| cbv.setOldValue(value1, false); |
| cbv.setIsDistributed(false); |
| cbv.setIsLoad(false); |
| cbv.setIsDestroy(true); |
| cbv.setIsUpdate(false); |
| // Test non-transactional localDestroy, expecting afterDestroy, |
| // non-distributed |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.localDestroy(key1, callBackArg); |
| if (!isPR()) |
| vCw.localDestroyMakeup(1); // Account for cacheWriter not begin called |
| assertTrue("Non-TX LocalDestroy Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.create(key1, value1); |
| cbv.suspendValidation(false); |
| // Test transactional localDestroy expecting afterDestroy, |
| // non-distributed |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.localDestroy(key1, callBackArg); |
| if (!isPR()) |
| vCw.localDestroyMakeup(1); // Account for cacheWriter not begin called |
| this.txMgr.commit(); |
| assertTrue("TX LocalDestroy Validation Assertion", cbv.passedValidation()); |
| |
| // Destroy => afterDestroy, distributed tests |
| cbv.setNewValue(null, true); |
| cbv.setOldValue(value1, false); |
| cbv.setIsDistributed(true); |
| cbv.setIsLoad(false); |
| cbv.setIsDestroy(true); |
| cbv.suspendValidation(true); |
| this.region.create(key1, value1); |
| cbv.suspendValidation(false); |
| // Test non-transactional Destroy, expecting afterDestroy, |
| // distributed |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.destroy(key1, callBackArg); |
| assertTrue("Non-TX Destroy Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.create(key1, value1); |
| cbv.suspendValidation(false); |
| // Test transactional Destroy, expecting afterDestroy, |
| // distributed |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.destroy(key1, callBackArg); |
| this.txMgr.commit(); |
| assertTrue("TX Destroy Validation Assertion", cbv.passedValidation()); |
| |
| // localInvalidate => afterInvalidate, non-distributed tests |
| cbv.setNewValue(null, true); |
| cbv.setOldValue(value1, false); |
| cbv.setIsDistributed(false); |
| cbv.setIsLoad(false); |
| cbv.setIsInvalidate(true); |
| cbv.setIsDestroy(false); |
| cbv.suspendValidation(true); |
| this.region.create(key1, value1); |
| cbv.suspendValidation(false); |
| // Test non-transactional localInvalidate, expecting afterInvalidate |
| // non-distributed |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.localInvalidate(key1, callBackArg); |
| assertTrue("Non-TX LocalInvalidate Validation Assertion", cbv.passedValidation()); |
| vCw.localDestroyMakeup(1); // Account for cacheWriter not begin called |
| cbv.suspendValidation(true); |
| this.region.put(key1, value1); |
| cbv.suspendValidation(false); |
| // Test transactional localInvalidate, expecting afterInvalidate |
| // non-distributed |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.localInvalidate(key1, callBackArg); |
| this.txMgr.commit(); |
| assertTrue("TX LocalInvalidate Validation Assertion", cbv.passedValidation()); |
| vCw.localDestroyMakeup(1); // Account for cacheWriter not begin called |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| |
| // Invalidate => afterInvalidate, distributed tests |
| cbv.setNewValue(null, true); |
| cbv.setOldValue(value1, false); |
| cbv.setIsDistributed(true); |
| cbv.setIsLoad(false); |
| cbv.suspendValidation(true); |
| this.region.create(key1, value1); |
| cbv.suspendValidation(false); |
| // Test non-transactional Invalidate, expecting afterInvalidate |
| // distributed |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.invalidate(key1, callBackArg); |
| vCw.localDestroyMakeup(1); // Account for cacheWriter not begin called |
| assertTrue("Non-TX Invalidate Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.put(key1, value1); |
| cbv.suspendValidation(false); |
| // Test transactional Invalidate, expecting afterInvalidate |
| // distributed |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.invalidate(key1, callBackArg); |
| this.txMgr.commit(); |
| vCw.localDestroyMakeup(1); // Account for cacheWriter not begin called |
| assertTrue("TX Invalidate Validation Assertion", cbv.passedValidation()); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| cbv.suspendValidation(false); |
| |
| // Create load Event tests |
| int loaderValCheck = 0; |
| cbv.setNewValue(loaderValCheck++, false); |
| cbv.setCallBackArg(null); |
| cbv.setOldValue(null, false); |
| cbv.setIsDistributed(true); |
| cbv.setIsCreate(true); |
| cbv.setIsUpdate(false); |
| cbv.setIsLoad(true); |
| // Test non-transactional load, expecting afterCreate distributed |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.get(key1); |
| assertTrue("Non-TX Invalidate Validation Assertion", cbv.passedValidation()); |
| vCl.validate(); |
| vCw.validate(); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| cbv.suspendValidation(false); |
| // Test transactional load, expecting afterCreate distributed |
| vCl.reset(); |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setNewValue(loaderValCheck++, false); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.get(key1); |
| this.txMgr.rollback(); |
| assertTrue("TX Invalidate Validation Assertion", cbv.passedValidation()); |
| vCw.validate(); |
| vCl.validateNoEvents(); |
| vCl.setExpectedCount(vCl.getCallCount() + 1); |
| |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setNewValue(loaderValCheck++, false); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.get(key1); |
| vCw.validate(); |
| vCw.reset(); |
| this.txMgr.commit(); |
| vCw.validateNoEvents(); |
| assertTrue("TX Invalidate Validation Assertion", cbv.passedValidation()); |
| vCl.validate(); |
| cbv.suspendValidation(true); |
| this.region.localDestroy(key1); |
| cbv.suspendValidation(false); |
| |
| // Update load Event tests |
| cbv.suspendValidation(true); |
| this.region.create(key1, null); |
| cbv.suspendValidation(false); |
| assertTrue(this.region.containsKey(key1)); |
| assertTrue(!this.region.containsValueForKey(key1)); |
| cbv.setNewValue(loaderValCheck++, false); |
| cbv.setOldValue(null, false); |
| cbv.setIsDistributed(true); |
| cbv.setCallBackArg(null); |
| cbv.setIsCreate(false); |
| cbv.setIsUpdate(true); |
| cbv.setIsLoad(true); |
| // Test non-transactional load, expecting afterUpdate distributed |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| this.region.get(key1); |
| assertTrue("Non-TX Invalidate Validation Assertion", cbv.passedValidation()); |
| vCw.validate(); |
| vCl.validate(); |
| cbv.suspendValidation(true); |
| this.region.invalidate(key1); |
| cbv.suspendValidation(false); |
| assertTrue(this.region.containsKey(key1)); |
| assertTrue(!this.region.containsValueForKey(key1)); |
| // Test transactional load, expecting afterUpdate distributed |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| cbv.setNewValue(loaderValCheck++, false); |
| this.region.get(key1); |
| vCw.validate(); |
| vCw.reset(); |
| this.txMgr.commit(); |
| vCw.validateNoEvents(); |
| vCl.validate(); |
| |
| cbv.suspendValidation(true); |
| this.region.invalidate(key1); |
| cbv.suspendValidation(false); |
| vCl.reset(); |
| this.txMgr.begin(); |
| cbv.setTXId(txMgr.getTransactionId()); |
| cbv.setExpectedCount(appCallCount++); |
| cbv.setNewValue(loaderValCheck++, false); |
| this.region.get(key1); |
| this.txMgr.rollback(); |
| assertTrue("TX Invalidate Validation Assertion", cbv.passedValidation()); |
| vCw.validate(); |
| vCl.validateNoEvents(); |
| } |
| |
| @Test |
| public void testEntryCount() throws CacheException { |
| LocalRegion reg1 = (LocalRegion) this.region; |
| |
| assertEquals(0, reg1.entryCount()); |
| reg1.create("key1", "value1"); |
| assertEquals(1, reg1.entryCount()); |
| reg1.create("key2", "value2"); |
| assertEquals(2, reg1.entryCount()); |
| reg1.localDestroy("key2"); |
| assertEquals(1, reg1.entryCount()); |
| |
| reg1.create("key3", "value3"); |
| assertEquals(2, reg1.entryCount()); |
| |
| this.txMgr.begin(); |
| this.region.create("key2", "value2"); |
| assertEquals(3, reg1.entryCount()); |
| reg1.localDestroy("key2"); |
| assertEquals(2, reg1.entryCount()); |
| |
| this.region.create("key2", "value2"); |
| assertEquals(3, reg1.entryCount()); |
| reg1.destroy("key2"); |
| assertEquals(2, reg1.entryCount()); |
| |
| reg1.localInvalidate("key1"); |
| assertEquals(2, reg1.entryCount()); |
| reg1.put("key1", "value2"); |
| assertEquals(2, reg1.entryCount()); |
| this.region.create("key2", "value2"); |
| assertEquals(3, reg1.entryCount()); |
| |
| reg1.localDestroy("key3"); |
| assertEquals(2, reg1.entryCount()); |
| reg1.create("key3", "value3"); |
| assertEquals(3, reg1.entryCount()); |
| |
| this.txMgr.rollback(); |
| |
| assertEquals(2, reg1.entryCount()); |
| } |
| |
| private void checkCollectionSize(int expectedSize) { |
| checkCollectionSize(expectedSize, expectedSize, expectedSize); |
| } |
| |
| private void checkCollectionSize(int expectedSize, int expectedRecSize) { |
| checkCollectionSize(expectedSize, expectedRecSize, expectedSize); |
| } |
| |
| private void checkCollectionSize(int expectedSize, int expectedRecSize, int expectedValuesSize) { |
| int size = 0; |
| for (Object key : this.region.entrySet(false)) { |
| size++; |
| } |
| assertEquals(expectedSize, size); |
| assertEquals(expectedSize, this.region.keySet().size()); |
| assertEquals(expectedValuesSize, this.region.values().size()); |
| assertEquals(expectedSize, this.region.entrySet(false).size()); |
| assertEquals(expectedRecSize, this.region.entrySet(true).size()); |
| } |
| |
| @Test |
| public void testCollections() throws CacheException { |
| Region<String, String> reg1 = this.region; |
| |
| checkSubRegionCollection(reg1); |
| |
| { |
| Collection nonTxKeys = reg1.keySet(); |
| Collection nonTxValues = reg1.values(); |
| this.txMgr.begin(); |
| reg1.create("key1", "value1"); |
| Collection txKeys = reg1.keySet(); |
| Collection txValues = reg1.values(); |
| /* |
| * [sumedh] No longer fail this scenario to avoid the overhead of ThreadLocal lookup in every |
| * iteration. Besides does not look to be a harmful usage in any case. |
| */ |
| try { |
| nonTxKeys.size(); |
| fail(); |
| } catch (IllegalStateException expected) { |
| TransactionId txid = this.txMgr.getTransactionId(); |
| assertEquals( |
| String.format( |
| "The Region collection is not transactional but is being used in a transaction %s.", |
| txid), |
| expected.getMessage()); |
| } |
| assertEquals(1, txKeys.size()); |
| try { |
| nonTxValues.size(); |
| fail(); |
| } catch (IllegalStateException expected) { |
| TransactionId txid = this.txMgr.getTransactionId(); |
| assertEquals( |
| String.format( |
| "The Region collection is not transactional but is being used in a transaction %s.", |
| txid), |
| expected.getMessage()); |
| } |
| assertEquals(1, txValues.size()); |
| assertTrue(txKeys.contains("key1")); |
| { |
| Iterator txIt = txKeys.iterator(); |
| assertTrue(txIt.hasNext()); |
| assertTrue(txIt.hasNext()); |
| assertEquals("key1", txIt.next()); |
| assertTrue(!txIt.hasNext()); |
| } |
| assertTrue(txValues.contains("value1")); |
| { |
| Iterator txIt = txValues.iterator(); |
| assertTrue(txIt.hasNext()); |
| assertTrue(txIt.hasNext()); |
| assertEquals("value1", txIt.next()); |
| assertTrue(!txIt.hasNext()); |
| } |
| reg1.invalidate("key1"); |
| assertEquals(1, txKeys.size()); |
| assertEquals(0, txValues.size()); |
| assertTrue(txKeys.contains("key1")); |
| assertTrue(!txValues.contains("value1")); |
| reg1.create("key2", "value2"); |
| reg1.create("key3", "value3"); |
| assertEquals(3, txKeys.size()); |
| assertEquals(2, txValues.size()); |
| reg1.put("key1", "value1"); |
| assertEquals(3, txKeys.size()); |
| assertEquals(3, txValues.size()); |
| reg1.localInvalidate("key2"); |
| assertEquals(2, txValues.size()); |
| reg1.invalidate("key1"); |
| assertEquals(1, txValues.size()); |
| reg1.destroy("key2"); |
| reg1.destroy("key3"); |
| assertEquals(1, txKeys.size()); |
| |
| reg1.destroy("key1"); |
| assertEquals(0, txKeys.size()); |
| assertTrue(!txKeys.contains("key1")); |
| Iterator txIt = txKeys.iterator(); |
| assertTrue(!txIt.hasNext()); |
| this.txMgr.rollback(); |
| try { |
| txKeys.size(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txKeys.isEmpty(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txKeys.contains("key1"); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txKeys.iterator(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| txIt.hasNext(); |
| } |
| { |
| this.txMgr.begin(); |
| reg1.create("key1", "value1"); |
| Collection txValues = reg1.values(); |
| assertEquals(1, txValues.size()); |
| assertTrue(txValues.contains("value1")); |
| { |
| Iterator txIt = txValues.iterator(); |
| assertTrue(txIt.hasNext()); |
| assertEquals("value1", txIt.next()); |
| assertTrue(!txIt.hasNext()); |
| } |
| reg1.destroy("key1"); |
| assertEquals(0, txValues.size()); |
| assertTrue(!txValues.contains("value1")); |
| assertTrue(!txValues.iterator().hasNext()); |
| assertTrue(!txValues.iterator().hasNext()); |
| this.txMgr.rollback(); |
| } |
| { |
| Collection nonTxEntries = reg1.entrySet(false); |
| this.txMgr.begin(); |
| reg1.create("key1", "value1"); |
| Collection txEntries = reg1.entrySet(false); |
| // non-TX collections can now be used in a transactional context |
| try { |
| nonTxEntries.size(); |
| fail(); |
| } catch (IllegalStateException expected) { |
| TransactionId txid = this.txMgr.getTransactionId(); |
| assertEquals( |
| String.format( |
| "The Region collection is not transactional but is being used in a transaction %s.", |
| txid), |
| expected.getMessage()); |
| } |
| assertEquals(1, txEntries.size()); |
| assertTrue(txEntries.contains(reg1.getEntry("key1"))); |
| { |
| Iterator txIt = txEntries.iterator(); |
| assertTrue(txIt.hasNext()); |
| assertTrue(txIt.hasNext()); |
| assertEquals(reg1.getEntry("key1"), txIt.next()); |
| assertTrue(!txIt.hasNext()); |
| assertTrue(!txIt.hasNext()); |
| } |
| reg1.destroy("key1"); |
| assertEquals(0, txEntries.size()); |
| assertTrue(!txEntries.iterator().hasNext()); |
| this.txMgr.rollback(); |
| } |
| { |
| Collection nonTxKeys = reg1.keySet(); |
| Collection nonTxValues = reg1.values(); |
| |
| assertEquals(0, nonTxKeys.size()); |
| assertEquals(0, nonTxValues.size()); |
| reg1.create("key1", "value1"); |
| assertEquals(1, nonTxKeys.size()); |
| assertEquals(1, nonTxValues.size()); |
| reg1.invalidate("key1"); |
| assertEquals(1, nonTxKeys.size()); |
| assertEquals(0, nonTxValues.size()); |
| |
| this.txMgr.begin(); |
| Collection txKeys = reg1.keySet(); |
| Collection txValues = reg1.values(); |
| assertEquals(1, txKeys.size()); |
| assertEquals(0, txValues.size()); |
| reg1.put("key1", "txValue1"); |
| assertEquals(1, txKeys.size()); |
| assertEquals(1, txValues.size()); |
| assertTrue(txValues.iterator().hasNext()); |
| assertEquals("txValue1", txValues.iterator().next()); |
| // non-TX collections can now be used in a transactional context |
| try { |
| nonTxValues.iterator().hasNext(); |
| } catch (IllegalStateException expected) { |
| TransactionId txid = this.txMgr.getTransactionId(); |
| assertEquals( |
| String.format( |
| "The Region collection is not transactional but is being used in a transaction %s.", |
| txid), |
| expected.getMessage()); |
| } |
| |
| reg1.localInvalidate("key1"); |
| assertEquals(0, txValues.size()); |
| assertTrue(!txValues.iterator().hasNext()); |
| this.txMgr.rollback(); |
| } |
| } |
| |
| protected void checkSubRegionCollection(Region<String, String> reg1) { |
| AttributesFactory<String, String> attributesFactory = new AttributesFactory<>(); |
| attributesFactory.setScope(Scope.DISTRIBUTED_NO_ACK); |
| |
| Region<String, String> sub1 = |
| this.region.createSubregion("collectionSub1", attributesFactory.create()); |
| |
| attributesFactory = new AttributesFactory<>(); |
| |
| Region<String, String> sub2 = |
| this.region.createSubregion("collectionSub2", attributesFactory.create()); |
| |
| attributesFactory = new AttributesFactory<>(); |
| attributesFactory.setScope(Scope.LOCAL); |
| |
| Region<String, String> sub2_1 = |
| sub2.createSubregion("collectionSub2_1", attributesFactory.create()); |
| |
| checkCollectionSize(0); |
| try { |
| this.region.keySet().iterator().next(); |
| fail(); |
| } catch (NoSuchElementException expected) { |
| assertNull(expected.getMessage()); |
| } |
| try { |
| this.region.values().iterator().next(); |
| fail(); |
| } catch (NoSuchElementException expected) { |
| assertNull(expected.getMessage()); |
| } |
| try { |
| this.region.entrySet().iterator().next(); |
| fail(); |
| } catch (NoSuchElementException expected) { |
| assertNull(expected.getMessage()); |
| } |
| reg1.create("key1", "value1"); |
| checkCollectionSize(1); |
| { |
| Iterator it = this.region.keySet().iterator(); |
| it.next(); |
| try { |
| it.next(); |
| fail(); |
| } catch (NoSuchElementException expected) { |
| assertNull(expected.getMessage()); |
| } |
| } |
| { |
| Iterator it = this.region.values().iterator(); |
| it.next(); |
| try { |
| it.next(); |
| fail(); |
| } catch (NoSuchElementException expected) { |
| assertNull(expected.getMessage()); |
| } |
| } |
| { |
| Iterator it = this.region.entrySet().iterator(); |
| it.next(); |
| try { |
| it.next(); |
| fail(); |
| } catch (NoSuchElementException expected) { |
| assertNull(expected.getMessage()); |
| } |
| } |
| |
| reg1.create("key2", "value2"); |
| checkCollectionSize(2); |
| reg1.localInvalidate("key2"); |
| checkCollectionSize(2, 2, 1); |
| reg1.localInvalidate("key1"); |
| checkCollectionSize(2, 2, 0); |
| reg1.localDestroy("key2"); |
| checkCollectionSize(1, 1, 0); |
| reg1.localDestroy("key1"); |
| checkCollectionSize(0); |
| |
| |
| // Non-TX recursive checks |
| sub2_1.create("key6", "value6"); |
| checkCollectionSize(0, 1); |
| assertEquals(0, sub2.entrySet(false).size()); |
| assertEquals(1, sub2.entrySet(true).size()); |
| assertEquals(1, sub2_1.entrySet(true).size()); |
| sub2.create("key5", "value5"); |
| checkCollectionSize(0, 2); |
| assertEquals(1, sub2.entrySet(false).size()); |
| assertEquals(2, sub2.entrySet(true).size()); |
| sub1.create("key4", "value4"); |
| checkCollectionSize(0, 3); |
| assertEquals(1, sub1.entrySet(false).size()); |
| assertEquals(1, sub1.entrySet(true).size()); |
| reg1.put("key1", "value1"); |
| checkCollectionSize(1, 4); |
| sub2.localDestroy("key5"); |
| checkCollectionSize(1, 3); |
| assertEquals(0, sub2.entrySet(false).size()); |
| assertEquals(1, sub2.entrySet(true).size()); |
| assertEquals(1, sub2_1.entrySet(false).size()); |
| assertEquals(1, sub2_1.entrySet(true).size()); |
| sub2_1.localDestroy("key6"); |
| checkCollectionSize(1, 2); |
| assertEquals(0, sub2.entrySet(false).size()); |
| assertEquals(0, sub2.entrySet(true).size()); |
| assertEquals(0, sub2_1.entrySet(false).size()); |
| sub1.localDestroy("key4"); |
| checkCollectionSize(1, 1); |
| assertEquals(0, sub1.entrySet(false).size()); |
| assertEquals(0, sub1.entrySet(true).size()); |
| |
| reg1.create("key3", "value3"); |
| sub1.create("key4", "value4"); |
| sub2.create("key5", "value5"); |
| sub2_1.create("key6", "value6"); |
| checkCollectionSize(2, 5); |
| |
| this.txMgr.begin(); |
| this.region.create("key2", "value2"); |
| checkCollectionSize(3, 6); |
| reg1.localDestroy("key2"); |
| checkCollectionSize(2, 5); |
| this.region.create("key2", "value2"); |
| checkCollectionSize(3, 6); |
| reg1.destroy("key2"); |
| checkCollectionSize(2, 5); |
| reg1.put("key1", "value2"); |
| checkCollectionSize(2, 5); |
| this.region.create("key2", "value2"); |
| checkCollectionSize(3, 6); |
| reg1.localDestroy("key3"); |
| checkCollectionSize(2, 5); |
| reg1.create("key3", "value3"); |
| checkCollectionSize(3, 6); |
| |
| // TX recursive checks |
| sub2.destroy("key5"); |
| checkCollectionSize(3, 5); |
| assertEquals(1, sub1.entrySet(false).size()); |
| assertEquals(1, sub1.entrySet(true).size()); |
| assertEquals(0, sub2.entrySet(false).size()); |
| assertEquals(1, sub2.entrySet(true).size()); |
| assertEquals(1, sub2_1.entrySet(false).size()); |
| assertEquals(1, sub2_1.entrySet(true).size()); |
| sub2_1.destroy("key6"); |
| checkCollectionSize(3, 4); |
| assertEquals(1, sub1.entrySet(false).size()); |
| assertEquals(1, sub1.entrySet(true).size()); |
| assertEquals(0, sub2.entrySet(false).size()); |
| assertEquals(0, sub2.entrySet(true).size()); |
| assertEquals(0, sub2_1.entrySet(false).size()); |
| assertEquals(0, sub2_1.entrySet(true).size()); |
| sub1.localDestroy("key4"); |
| checkCollectionSize(3, 3); |
| assertEquals(0, sub1.entrySet(false).size()); |
| assertEquals(0, sub1.entrySet(true).size()); |
| assertEquals(0, sub2.entrySet(false).size()); |
| assertEquals(0, sub2.entrySet(true).size()); |
| assertEquals(0, sub2_1.entrySet(false).size()); |
| assertEquals(0, sub2_1.entrySet(true).size()); |
| sub2.put("key5", "value5"); |
| checkCollectionSize(3, 4); |
| assertEquals(0, sub1.entrySet(false).size()); |
| assertEquals(0, sub1.entrySet(true).size()); |
| assertEquals(1, sub2.entrySet(false).size()); |
| assertEquals(1, sub2.entrySet(true).size()); |
| assertEquals(0, sub2_1.entrySet(false).size()); |
| assertEquals(0, sub2_1.entrySet(true).size()); |
| sub2_1.put("key6", "value6"); |
| checkCollectionSize(3, 5); |
| assertEquals(0, sub1.entrySet(false).size()); |
| assertEquals(0, sub1.entrySet(true).size()); |
| assertEquals(1, sub2.entrySet(false).size()); |
| assertEquals(2, sub2.entrySet(true).size()); |
| assertEquals(1, sub2_1.entrySet(false).size()); |
| assertEquals(1, sub2_1.entrySet(true).size()); |
| sub1.put("key4", "value4"); |
| checkCollectionSize(3, 6); |
| assertEquals(1, sub1.entrySet(false).size()); |
| assertEquals(1, sub1.entrySet(true).size()); |
| assertEquals(1, sub2.entrySet(false).size()); |
| assertEquals(2, sub2.entrySet(true).size()); |
| assertEquals(1, sub2_1.entrySet(false).size()); |
| assertEquals(1, sub2_1.entrySet(true).size()); |
| sub2_1.put("key7", "value7"); |
| checkCollectionSize(3, 7); |
| assertEquals(1, sub1.entrySet(false).size()); |
| assertEquals(1, sub1.entrySet(true).size()); |
| assertEquals(1, sub2.entrySet(false).size()); |
| assertEquals(3, sub2.entrySet(true).size()); |
| assertEquals(2, sub2_1.entrySet(false).size()); |
| assertEquals(2, sub2_1.entrySet(true).size()); |
| |
| this.txMgr.rollback(); |
| checkCollectionSize(2, 5); |
| |
| // disabling these in a TX because they throw and don't work now! |
| // this.txMgr.begin(); |
| sub2.destroyRegion(); |
| checkCollectionSize(2, 3); |
| sub1.destroyRegion(); |
| checkCollectionSize(2); |
| |
| reg1.localDestroy("key1"); |
| reg1.localDestroy("key3"); |
| checkCollectionSize(0); |
| } |
| |
| @Test |
| public void testLoader() throws CacheException { |
| AttributesMutator<String, String> mutator = this.region.getAttributesMutator(); |
| mutator.setCacheLoader(new CacheLoader<String, String>() { |
| int count = 0; |
| |
| @Override |
| public String load(LoaderHelper helper) throws CacheLoaderException { |
| count++; |
| return "LV " + count; |
| } |
| |
| @Override |
| public void close() {} |
| }); |
| LocalRegion reg1 = (LocalRegion) this.region; |
| if (isPR()) |
| ((PartitionedRegion) reg1).setHaveCacheLoader(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 1", reg1.get("key1")); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 1", reg1.getEntry("key1").getValue()); |
| reg1.localDestroy("key1"); |
| |
| // TX load: only TX |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 2", reg1.get("key1")); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 2", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| assertTrue(!reg1.containsKey("key1")); |
| // assertIndexDetailsEquals("LV 2", reg1.getEntry("key1").getValue()); |
| // reg1.localDestroy("key1"); |
| // TX load: commit check |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 3", reg1.get("key1")); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 3", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 3", reg1.getEntry("key1").getValue()); |
| reg1.localDestroy("key1"); |
| // TX load YES conflict: no-initial state, tx create, committed load |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| this.txMgr.begin(); |
| reg1.create("key1", "txValue"); |
| assertEquals("txValue", reg1.getEntry("key1").getValue()); |
| tx = txMgrImpl.pauseTransaction(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 4", reg1.get("key1")); |
| assertTrue(reg1.containsKey("key1")); |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals("txValue", reg1.getEntry("key1").getValue()); |
| assertEquals("txValue", reg1.get("key1")); |
| try { |
| this.txMgr.commit(); |
| fail("Should have thrown a commit conflict"); |
| } catch (CommitConflictException cce) { |
| // this is what we want |
| } |
| assertEquals("LV 4", reg1.getEntry("key1").getValue()); |
| assertEquals("LV 4", reg1.get("key1")); |
| reg1.localDestroy("key1"); |
| } |
| // TX load no conflict: load initial state, tx update |
| assertEquals("LV 5", reg1.get("key1")); |
| this.txMgr.begin(); |
| reg1.put("key1", "txValue"); |
| assertEquals("txValue", reg1.get("key1")); |
| assertEquals("txValue", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); // no conflict! Make sure committed value overrode initial state |
| assertEquals("txValue", reg1.getEntry("key1").getValue()); |
| assertEquals("txValue", reg1.get("key1")); |
| reg1.localDestroy("key1"); |
| // TX load no conflict: load initial state, tx load |
| assertEquals("LV 6", reg1.get("key1")); |
| this.txMgr.begin(); |
| reg1.localInvalidate("key1"); |
| assertEquals("LV 7", reg1.get("key1")); |
| assertEquals("LV 7", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); // no conflict! Make sure committed value overrode initial state |
| assertEquals("LV 7", reg1.getEntry("key1").getValue()); |
| assertEquals("LV 7", reg1.get("key1")); |
| reg1.localDestroy("key1"); |
| |
| // TX load no conflict: no initial state, tx load, committed create |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| this.txMgr.begin(); |
| assertEquals("LV 8", reg1.get("key1")); |
| assertEquals("LV 8", reg1.getEntry("key1").getValue()); |
| tx = txMgrImpl.pauseTransaction(); |
| assertTrue(!reg1.containsKey("key1")); |
| reg1.create("key1", "txValue"); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("txValue", reg1.get("key1")); |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals("LV 8", reg1.getEntry("key1").getValue()); |
| try { |
| this.txMgr.commit(); // should conflict |
| fail("Should have thrown cce"); |
| } catch (CommitConflictException cce) { |
| // this is what we want |
| } |
| assertEquals("txValue", reg1.getEntry("key1").getValue()); |
| assertEquals("txValue", reg1.get("key1")); |
| reg1.localDestroy("key1"); |
| } |
| // TX load conflict: no-inital state, tx load->update, committed update |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TransactionId txId = null; |
| this.txMgr.begin(); |
| reg1.create("key1", "txValue"); |
| txId = txMgrImpl.suspend(); |
| assertTrue(!reg1.containsKey("key1")); |
| // new transaction, load(create) + put |
| this.txMgr.begin(); |
| assertEquals("LV 9", reg1.get("key1")); |
| assertEquals("LV 9", reg1.getEntry("key1").getValue()); |
| reg1.put("key1", "txValue2"); |
| assertEquals("txValue2", reg1.get("key1")); |
| assertEquals("txValue2", reg1.getEntry("key1").getValue()); |
| this.txMgr.commit(); |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("txValue2", reg1.get("key1")); |
| assertEquals("txValue2", reg1.getEntry("key1").getValue()); |
| txMgrImpl.resume(txId); |
| assertEquals("txValue", reg1.getEntry("key1").getValue()); |
| assertEquals("txValue", reg1.get("key1")); |
| try { |
| this.txMgr.commit(); |
| fail("expected CommitConflictException!"); |
| } catch (CommitConflictException expected) { |
| } |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("txValue2", reg1.get("key1")); |
| assertEquals("txValue2", reg1.getEntry("key1").getValue()); |
| reg1.localDestroy("key1"); |
| } |
| |
| // TX load repeat: no-initial state, tx load->get |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 10", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 10", reg1.getEntry("key1").getValue()); |
| assertEquals("LV 10", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 10", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: no-initial state, tx load->localDestory->load |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 11", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 11", reg1.getEntry("key1").getValue()); |
| reg1.localDestroy("key1"); |
| assertEquals("LV 12", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 12", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: no-initial state: tx load->destroy->load |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 13", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 13", reg1.getEntry("key1").getValue()); |
| reg1.destroy("key1"); |
| assertEquals("LV 14", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 14", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: no-initial state, tx load->localInvalidate->load |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 15", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 15", reg1.getEntry("key1").getValue()); |
| reg1.localInvalidate("key1"); |
| assertEquals("LV 16", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 16", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: no-initial, tx load->invalidate->load |
| this.txMgr.begin(); |
| assertTrue(!reg1.containsKey("key1")); |
| assertEquals("LV 17", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 17", reg1.getEntry("key1").getValue()); |
| reg1.invalidate("key1"); |
| assertEquals("LV 18", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 18", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: invalid entry initial state, tx load->get |
| reg1.create("key1", null); |
| this.txMgr.begin(); |
| assertTrue(reg1.containsKey("key1")); |
| assertNull(reg1.getEntry("key1").getValue()); |
| assertEquals("LV 19", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 19", reg1.getEntry("key1").getValue()); |
| assertEquals("LV 19", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 19", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: invalid entry initial state, tx load->localDestory->load |
| this.txMgr.begin(); |
| assertTrue(reg1.containsKey("key1")); |
| assertNull(reg1.getEntry("key1").getValue()); |
| assertEquals("LV 20", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 20", reg1.getEntry("key1").getValue()); |
| reg1.localDestroy("key1"); |
| assertEquals("LV 21", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 21", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: invalid entry initial state: tx load->destroy->load |
| this.txMgr.begin(); |
| assertTrue(reg1.containsKey("key1")); |
| assertNull(reg1.getEntry("key1").getValue()); |
| assertEquals("LV 22", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 22", reg1.getEntry("key1").getValue()); |
| reg1.destroy("key1"); |
| assertEquals("LV 23", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 23", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: invalid entry initial state, tx load->localInvalidate->load |
| this.txMgr.begin(); |
| assertTrue(reg1.containsKey("key1")); |
| assertNull(reg1.getEntry("key1").getValue()); |
| assertEquals("LV 24", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 24", reg1.getEntry("key1").getValue()); |
| reg1.localInvalidate("key1"); |
| assertEquals("LV 25", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 25", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // TX load repeat: invalid entry initial state, tx load->invalidate->load |
| this.txMgr.begin(); |
| assertTrue(reg1.containsKey("key1")); |
| assertNull(reg1.getEntry("key1").getValue()); |
| assertEquals("LV 26", reg1.get("key1")); // first invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 26", reg1.getEntry("key1").getValue()); |
| reg1.invalidate("key1"); |
| assertEquals("LV 27", reg1.get("key1")); // second invocation |
| assertTrue(reg1.containsKey("key1")); |
| assertEquals("LV 27", reg1.getEntry("key1").getValue()); |
| this.txMgr.rollback(); |
| |
| // Make sure a load does not conflict with the region being destroyed |
| this.txMgr.begin(); |
| assertEquals("LV 28", reg1.get("key2")); |
| |
| this.txMgr.commit(); |
| reg1.localDestroyRegion(); // non-tx region op |
| // reg1 is now destroyed |
| } |
| |
| @Test |
| public void testStats() throws CacheException { |
| final int SLEEP_MS = 250; |
| // final int OP_TIME = 0; // ns // changed form 10 to 0 because on fater platforms |
| // and low resolution clocks this test will fail. |
| final CachePerfStats stats = this.cache.getCachePerfStats(); |
| |
| class statsValidator { |
| private long txSuccessLifeTime; |
| private long txFailedLifeTime; |
| private long txRollbackLifeTime; |
| private int txCommits; |
| private int txFailures; |
| private int txRollbacks; |
| private long txCommitTime; |
| private long txFailureTime; |
| private long txRollbackTime; |
| private int txCommitChanges; |
| private int txFailureChanges; |
| private int txRollbackChanges; |
| |
| private CachePerfStats stats; |
| |
| private statsValidator(CachePerfStats stats) { |
| this.stats = stats; |
| } |
| |
| private void reset() { |
| this.txSuccessLifeTime = this.stats.getTxSuccessLifeTime(); |
| this.txFailedLifeTime = this.stats.getTxFailedLifeTime(); |
| this.txRollbackLifeTime = this.stats.getTxRollbackLifeTime(); |
| this.txCommits = this.stats.getTxCommits(); |
| this.txFailures = this.stats.getTxFailures(); |
| this.txRollbacks = this.stats.getTxRollbacks(); |
| this.txCommitTime = this.stats.getTxCommitTime(); |
| this.txFailureTime = this.stats.getTxFailureTime(); |
| this.txRollbackTime = this.stats.getTxRollbackTime(); |
| this.txCommitChanges = this.stats.getTxCommitChanges(); |
| this.txFailureChanges = this.stats.getTxFailureChanges(); |
| this.txRollbackChanges = this.stats.getTxRollbackChanges(); |
| } |
| |
| private void setTxSuccessLifeTime(long txSuccessLifeTime) { |
| this.txSuccessLifeTime = txSuccessLifeTime; |
| } |
| |
| private void setTxFailedLifeTime(long txFailedLifeTime) { |
| this.txFailedLifeTime = txFailedLifeTime; |
| } |
| |
| private void setTxRollbackLifeTime(long txRollbackLifeTime) { |
| this.txRollbackLifeTime = txRollbackLifeTime; |
| } |
| |
| private void setTxCommits(int txCommits) { |
| this.txCommits = txCommits; |
| } |
| |
| private void setTxFailures(int txFailures) { |
| this.txFailures = txFailures; |
| } |
| |
| private void setTxRollbacks(int txRollbacks) { |
| this.txRollbacks = txRollbacks; |
| } |
| |
| private void setTxCommitTime(long txCommitTime) { |
| this.txCommitTime = txCommitTime; |
| } |
| |
| private void setTxFailureTime(long txFailureTime) { |
| this.txFailureTime = txFailureTime; |
| } |
| |
| private void setTxRollbackTime(long txRollbackTime) { |
| this.txRollbackTime = txRollbackTime; |
| } |
| |
| private void setTxCommitChanges(int txCommitChanges) { |
| this.txCommitChanges = txCommitChanges; |
| } |
| |
| private void setTxFailureChanges(int txFailureChanges) { |
| this.txFailureChanges = txFailureChanges; |
| } |
| |
| private void setTxRollbackChanges(int txRollbackChanges) { |
| this.txRollbackChanges = txRollbackChanges; |
| } |
| |
| private void assertValid() { |
| assertEquals(this.txRollbacks, this.stats.getTxRollbacks()); |
| assertEquals(this.txRollbackChanges, this.stats.getTxRollbackChanges()); |
| if (Boolean |
| .getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "cache.enable-time-statistics")) { |
| assertTrue(this.txRollbackTime <= this.stats.getTxRollbackTime()); |
| // assertTrue(this.txRollbackLifeTime+((SLEEP_MS-10)*1000000) <= |
| // this.stats.getTxRollbackLifeTime()); |
| assertTrue( |
| "RollbackLifeTime " + this.txRollbackLifeTime + " is not <= " |
| + this.stats.getTxRollbackLifeTime(), |
| this.txRollbackLifeTime <= this.stats.getTxRollbackLifeTime()); |
| assertTrue(this.txCommitTime <= this.stats.getTxCommitTime()); |
| assertTrue(this.txSuccessLifeTime <= this.stats.getTxSuccessLifeTime()); |
| assertTrue(this.txFailureTime <= this.stats.getTxFailureTime()); |
| assertTrue( |
| "FailedLifeTime " + this.txFailedLifeTime + " is not <= " |
| + this.stats.getTxFailedLifeTime(), |
| this.txFailedLifeTime <= this.stats.getTxFailedLifeTime()); |
| } |
| |
| assertEquals(this.txCommits, this.stats.getTxCommits()); |
| assertEquals(this.txCommitChanges, this.stats.getTxCommitChanges()); |
| |
| assertEquals(this.txFailures, this.stats.getTxFailures()); |
| assertEquals(this.txFailureChanges, this.stats.getTxFailureChanges()); |
| } |
| } |
| |
| statsValidator statsVal = new statsValidator(stats); |
| // Zero and non-zero rollback stats test |
| int i; |
| long testRollbackLifeTime = 0, testTotalTx = 0; |
| for (i = 0; i < 2; ++i) { |
| statsVal.reset(); |
| statsVal.setTxRollbacks(stats.getTxRollbacks() + 1); |
| statsVal.setTxRollbackLifeTime(stats.getTxRollbackLifeTime() + ((SLEEP_MS - 20) * 1000000)); |
| final long beforeBegin = NanoTimer.getTime(); |
| this.txMgr.begin(); |
| final long afterBegin = NanoTimer.getTime(); |
| pause(SLEEP_MS); |
| if (i > 0) { |
| statsVal.setTxRollbackChanges(stats.getTxRollbackChanges() + 2); |
| this.region.put("stats1", "stats rollback1"); |
| this.region.put("stats2", "stats rollback2"); |
| } |
| statsVal.setTxRollbackTime(stats.getTxRollbackTime()); |
| final long beforeRollback = NanoTimer.getTime(); |
| this.txMgr.rollback(); |
| final long afterRollback = NanoTimer.getTime(); |
| final long statsRollbackLifeTime = stats.getTxRollbackLifeTime(); |
| testRollbackLifeTime += beforeRollback - afterBegin; |
| // bruce - time based stats are disabled by default |
| String p = (String) cache.getDistributedSystem().getProperties() |
| .get(GeodeGlossary.GEMFIRE_PREFIX + "enable-time-statistics"); |
| if (p != null && Boolean.getBoolean(p)) { |
| assertTrue("Local RollbackLifeTime assertion: " + testRollbackLifeTime + " is not <= " |
| + statsRollbackLifeTime, testRollbackLifeTime <= statsRollbackLifeTime); |
| } |
| testTotalTx += afterRollback - beforeBegin; |
| final long totalTXMinusRollback = testTotalTx - stats.getTxRollbackTime(); |
| if (Boolean.getBoolean(GeodeGlossary.GEMFIRE_PREFIX + "cache.enable-time-statistics")) { |
| assertTrue("Total Tx Minus Rollback assertion: " + totalTXMinusRollback + " is not >= " |
| + statsRollbackLifeTime, totalTXMinusRollback >= statsRollbackLifeTime); |
| } |
| statsVal.assertValid(); |
| } |
| |
| // Zero and non-zero commit stats test |
| for (i = 0; i < 2; ++i) { |
| statsVal.reset(); |
| statsVal.setTxCommits(stats.getTxCommits() + 1); |
| statsVal.setTxSuccessLifeTime(stats.getTxSuccessLifeTime() + ((SLEEP_MS - 10) * 1000000)); |
| this.txMgr.begin(); |
| pause(SLEEP_MS); |
| if (i > 0) { |
| statsVal.setTxCommitChanges(stats.getTxCommitChanges() + 2); |
| this.region.put("stats1", "commit1"); |
| this.region.put("stats2", "commit2"); |
| } |
| try { |
| statsVal.setTxCommitTime(stats.getTxCommitTime()); |
| this.txMgr.commit(); |
| } catch (CommitConflictException ex) { |
| fail("unexpected " + ex); |
| } |
| statsVal.assertValid(); |
| } |
| |
| // Non-zero failed commit stats |
| TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| statsVal.reset(); |
| statsVal.setTxFailures(stats.getTxFailures() + 1); |
| statsVal.setTxFailureChanges(stats.getTxFailureChanges() + 2); |
| statsVal.setTxFailedLifeTime(stats.getTxFailedLifeTime() + ((SLEEP_MS - 20) * 1000000)); |
| this.region.put("stats3", "stats fail3"); |
| this.txMgr.begin(); |
| this.region.put("stats1", "stats fail1"); |
| this.region.put("stats2", "stats fail2"); |
| try { |
| this.region.create("stats3", "try stats3"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException ok) { |
| } |
| // begin other tx simulation |
| TXStateProxy tx = txMgrImpl.pauseTransaction(); |
| this.region.put("stats1", "stats success1"); |
| this.region.put("stats2", "stats success2"); |
| txMgrImpl.unpauseTransaction(tx); |
| // end other tx simulation |
| pause(SLEEP_MS); |
| try { |
| statsVal.setTxFailureTime(stats.getTxFailureTime()); |
| this.txMgr.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| // expected failure |
| } |
| statsVal.assertValid(); |
| } |
| |
| @Test |
| public void testCacheStats() throws CacheException { |
| CachePerfStats cacheStats = this.cache.getCachePerfStats(); |
| // quick sanity check to make sure perf stats work non-tx |
| long creates; |
| long destroys; |
| long puts; |
| long invalidates; |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.region.create("key1", "value1"); |
| assertEquals(creates + 1, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts + 1, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.region.put("key1", "value2"); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts + 1, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.region.invalidate("key1"); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts, cacheStats.getPuts()); |
| assertEquals(invalidates + 1, cacheStats.getInvalidates()); |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.region.destroy("key1"); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys + 1, cacheStats.getDestroys()); |
| assertEquals(puts, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| |
| // now make sure they do not change from tx ops and from rollbacks |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.txMgr.begin(); |
| this.region.create("key1", "value1"); |
| this.region.put("key1", "value2"); |
| this.region.invalidate("key1"); |
| this.region.put("key1", "value3"); |
| this.region.localInvalidate("key1"); |
| this.region.put("key1", "value4"); |
| this.region.localDestroy("key1"); |
| this.region.put("key1", "value5"); |
| this.region.destroy("key1"); |
| this.txMgr.rollback(); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| |
| // now make sure they do change when a commit is done |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.txMgr.begin(); |
| this.region.create("key1", "value1"); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(puts, cacheStats.getPuts()); |
| this.txMgr.commit(); |
| assertEquals(creates + 1, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts + 1, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.txMgr.begin(); |
| this.region.put("key1", "value1"); |
| assertEquals(puts, cacheStats.getPuts()); |
| this.txMgr.commit(); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts + 1, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.txMgr.begin(); |
| this.region.localInvalidate("key1"); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| this.txMgr.commit(); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| assertEquals(puts, cacheStats.getPuts()); |
| assertEquals(invalidates + 1, cacheStats.getInvalidates()); |
| |
| creates = cacheStats.getCreates(); |
| destroys = cacheStats.getDestroys(); |
| puts = cacheStats.getPuts(); |
| invalidates = cacheStats.getInvalidates(); |
| this.txMgr.begin(); |
| this.region.localDestroy("key1"); |
| assertEquals(destroys, cacheStats.getDestroys()); |
| this.txMgr.commit(); |
| assertEquals(creates, cacheStats.getCreates()); |
| assertEquals(destroys + 1, cacheStats.getDestroys()); |
| assertEquals(puts, cacheStats.getPuts()); |
| assertEquals(invalidates, cacheStats.getInvalidates()); |
| } |
| |
| private void pause(int msWait) { |
| try { |
| Thread.sleep(msWait); |
| } catch (InterruptedException ignore) { |
| fail("interrupted"); |
| } |
| } |
| |
| @Test |
| public void testPauseUnpause() { |
| TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| assertTrue(!this.txMgr.exists()); |
| assertEquals(null, txMgrImpl.pauseTransaction()); |
| TXStateProxy txProxy = null; |
| txMgrImpl.unpauseTransaction(txProxy); |
| assertTrue(!this.txMgr.exists()); |
| |
| this.txMgr.begin(); |
| TransactionId origId = this.txMgr.getTransactionId(); |
| assertTrue(this.txMgr.exists()); |
| { |
| TXStateProxy tx = txMgrImpl.pauseTransaction(); |
| assertTrue(!this.txMgr.exists()); |
| assertThatThrownBy(() -> this.txMgr.begin()).isInstanceOf(IllegalStateException.class); |
| assertTrue(!this.txMgr.exists()); |
| txMgrImpl.unpauseTransaction(tx); |
| } |
| assertTrue(this.txMgr.exists()); |
| assertEquals(origId, this.txMgr.getTransactionId()); |
| this.txMgr.rollback(); |
| } |
| |
| @Test |
| public void testSuspendResume() { |
| TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| assertTrue(!this.txMgr.exists()); |
| assertEquals(null, txMgrImpl.pauseTransaction()); |
| TXStateProxy txProxy = null; |
| txMgrImpl.unpauseTransaction(txProxy); |
| assertTrue(!this.txMgr.exists()); |
| |
| this.txMgr.begin(); |
| TransactionId origId = this.txMgr.getTransactionId(); |
| assertTrue(this.txMgr.exists()); |
| { |
| TXStateProxy tx = txMgrImpl.internalSuspend(); |
| assertTrue(!this.txMgr.exists()); |
| this.txMgr.begin(); |
| try { |
| txMgrImpl.internalResume(tx); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| LogService.getLogger().info("expected ", expected); |
| } |
| this.txMgr.rollback(); |
| assertTrue(!this.txMgr.exists()); |
| txMgrImpl.internalResume(tx); |
| } |
| assertTrue(this.txMgr.exists()); |
| assertEquals(origId, this.txMgr.getTransactionId()); |
| this.txMgr.rollback(); |
| } |
| |
| @Test |
| public void testPublicSuspendResume() { |
| CacheTransactionManager txMgr = this.txMgr; |
| assertTrue(!this.txMgr.exists()); |
| assertEquals(null, txMgr.suspend()); |
| TransactionId txId = null; |
| try { |
| txMgr.resume(txId); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException e) { |
| } |
| assertTrue(!this.txMgr.exists()); |
| |
| this.txMgr.begin(); |
| TransactionId origId = this.txMgr.getTransactionId(); |
| assertTrue(this.txMgr.exists()); |
| { |
| TransactionId tx = txMgr.suspend(); |
| assertTrue(!this.txMgr.exists()); |
| this.txMgr.begin(); |
| try { |
| txMgr.resume(tx); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException expected) { |
| } |
| this.txMgr.rollback(); |
| assertTrue(!this.txMgr.exists()); |
| txMgr.resume(tx); |
| } |
| assertTrue(this.txMgr.exists()); |
| assertEquals(origId, this.txMgr.getTransactionId()); |
| this.txMgr.rollback(); |
| |
| } |
| |
| @Test |
| public void testCheckNoTX() { |
| { |
| AttributesFactory<String, String> af = new AttributesFactory<>(); |
| af.setScope(Scope.GLOBAL); |
| Region<String, String> gr = null; |
| try { |
| gr = this.cache.createRegion("GLOBALTXTest", af.create()); |
| } catch (CacheException ex) { |
| fail("did not expect " + ex); |
| } |
| try { |
| gr.put("foo", "bar1"); |
| } catch (Exception ex) { |
| fail("did not expect " + ex); |
| } |
| this.txMgr.begin(); |
| try { |
| gr.put("foo", "bar2"); |
| fail("expected UnsupportedOperationException"); |
| } catch (UnsupportedOperationException expected) { |
| } catch (Exception ex) { |
| fail("did not expect " + ex); |
| } |
| this.txMgr.rollback(); |
| } |
| |
| |
| { |
| DiskStoreFactory dsf = this.cache.createDiskStoreFactory(); |
| dsf.create("testCheckNoTX"); |
| AttributesFactory<String, String> af = new AttributesFactory<>(); |
| af.setScope(Scope.LOCAL); |
| af.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); |
| af.setDiskStoreName("testCheckNoTX"); |
| Region<String, String> dr = null; |
| try { |
| dr = this.cache.createRegion("DiskTXTest", af.create()); |
| } catch (CacheException ex) { |
| fail("did not expect " + ex); |
| } |
| try { |
| try { |
| dr.put("foo", "bar1"); |
| } catch (Exception ex) { |
| fail("did not expect " + ex); |
| } |
| this.txMgr.begin(); |
| try { |
| dr.put("foo", "bar2"); |
| fail("expected UnsupportedOperationException"); |
| } catch (UnsupportedOperationException expected) { |
| } catch (Exception ex) { |
| fail("did not expect " + ex); |
| } |
| this.txMgr.rollback(); |
| } finally { |
| dr.localDestroyRegion(); |
| } |
| } |
| } |
| |
| @Test |
| public void valuesRepeatableReadDoesNotIncludeTombstones() throws Exception { |
| Region newRegion = createRegion("newRegion", true); |
| newRegion.put("key1", "value1"); |
| newRegion.destroy("key1"); // creates a tombstone |
| |
| txMgr.begin(); // tx1 |
| newRegion.values().toArray(); // this is a repeatable read, does not read tombstone |
| TransactionId txId = txMgr.suspend(); |
| |
| txMgr.begin(); // tx2 |
| newRegion.put("key1", "newValue"); |
| txMgr.commit(); |
| |
| txMgr.resume(txId); |
| newRegion.put("key1", "value1"); |
| txMgr.commit(); |
| assertThat(newRegion.get("key1")).isEqualTo("value1"); |
| } |
| |
| @Test |
| public void keySetRepeatableReadDoesNotIncludeTombstones() throws Exception { |
| Region newRegion = createRegion("newRegion", true); |
| newRegion.put("key1", "value1"); |
| newRegion.destroy("key1"); // creates a tombstone |
| |
| txMgr.begin(); // tx1 |
| newRegion.keySet().toArray(); // this is a repeatable read, does not read tombstone |
| TransactionId txId = txMgr.suspend(); |
| |
| txMgr.begin(); // tx2 |
| newRegion.put("key1", "newValue"); |
| txMgr.commit(); |
| |
| txMgr.resume(txId); |
| newRegion.put("key1", "value1"); |
| txMgr.commit(); |
| assertThat(newRegion.get("key1")).isEqualTo("value1"); |
| } |
| |
| @Test |
| public void valuesRepeatableReadIncludesInvalidates() throws Exception { |
| Region newRegion = createRegion("newRegion", true); |
| newRegion.put("key1", "value1"); |
| newRegion.invalidate("key1"); |
| |
| txMgr.begin(); // tx1 |
| newRegion.values().toArray(); // this is a repeatable read, reads invalidate |
| TransactionId txId = txMgr.suspend(); |
| |
| txMgr.begin(); // tx2 |
| newRegion.put("key1", "newValue"); |
| txMgr.commit(); |
| |
| txMgr.resume(txId); |
| newRegion.put("key1", "value1"); |
| assertThatThrownBy(() -> txMgr.commit()).isExactlyInstanceOf(CommitConflictException.class); |
| assertThat(newRegion.get("key1")).isEqualTo("newValue"); |
| } |
| |
| @Test |
| public void keySetRepeatableReadIncludesInvalidates() throws Exception { |
| Region newRegion = createRegion("newRegion", true); |
| newRegion.put("key1", "value1"); |
| newRegion.invalidate("key1"); |
| |
| txMgr.begin(); // tx1 |
| newRegion.keySet().toArray(); // this is a repeatable read, reads invalidate |
| TransactionId txId = txMgr.suspend(); |
| |
| txMgr.begin(); // tx2 |
| newRegion.put("key1", "newValue"); |
| txMgr.commit(); |
| |
| txMgr.resume(txId); |
| newRegion.put("key1", "value1"); |
| assertThatThrownBy(() -> txMgr.commit()).isExactlyInstanceOf(CommitConflictException.class); |
| assertThat(newRegion.get("key1")).isEqualTo("newValue"); |
| } |
| |
| @Test |
| public void testRepeatableRead() throws CacheException { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| |
| // try repeating a get and make sure it doesn't cause a conflict |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals("value1", this.region.get("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| |
| assertEquals("value1", this.region.get("key1")); |
| txMgrImpl.commit(); |
| |
| // try repeating a get and modify the entry and make sure it causes a conflict |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals("value1", this.region.get("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals("value1", this.region.get("key1")); |
| this.region.put("key1", "value3"); |
| assertEquals("value3", this.region.get("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try repeating a getEntry and make sure it doesn't cause a conflict |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| this.region.getEntry("key1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| |
| assertEquals("value1", this.region.get("key1")); |
| txMgrImpl.commit(); |
| |
| // try repeating a getEntry and modify the entry and make sure it causes a conflict |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| this.region.getEntry("key1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| this.region.put("key1", "value3"); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try RR when entry fetched using entrySet |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| this.region.get("key1"); // bootstrap the tx, entrySet does not |
| this.region.entrySet(false).iterator().next(); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| |
| assertEquals("value1", this.region.get("key1")); |
| txMgrImpl.commit(); |
| |
| // try RRW->CONFLICT when entry fetched using entrySet |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| this.region.get("key1"); // bootstrap the tx, entrySet does not |
| this.region.entrySet(false).iterator().next(); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals("value1", this.region.get("key1")); |
| this.region.put("key1", "value3"); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try containsKey |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(true, this.region.containsKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(true, this.region.containsKey("key1")); |
| txMgrImpl.commit(); |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(true, this.region.containsKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(true, this.region.containsKey("key1")); |
| this.region.put("key1", "value3"); |
| assertEquals(true, this.region.containsKey("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| // try containsValueForKey |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(true, this.region.containsValueForKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(true, this.region.containsValueForKey("key1")); |
| txMgrImpl.commit(); |
| this.region.put("key1", "value1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(true, this.region.containsValueForKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(true, this.region.containsValueForKey("key1")); |
| this.region.put("key1", "value3"); |
| assertEquals(true, this.region.containsValueForKey("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // now try the same things but with no entry in committed state at |
| // the time of the first read |
| // try repeating a get and make sure it doesn't cause a conflict |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(null, this.region.get("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| |
| assertEquals(null, this.region.get("key1")); |
| txMgrImpl.commit(); |
| |
| // try repeating a get and modify the entry and make sure it causes a conflict |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(null, this.region.get("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(null, this.region.get("key1")); |
| this.region.put("key1", "value3"); |
| assertEquals("value3", this.region.get("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try repeating a getEntry and make sure it doesn't cause a conflict |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(null, this.region.getEntry("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| |
| assertEquals(null, this.region.getEntry("key1")); |
| txMgrImpl.commit(); |
| |
| // try repeating a getEntry and modify the entry and make sure it causes a conflict |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(null, this.region.getEntry("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(null, this.region.getEntry("key1")); |
| this.region.put("key1", "value3"); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try containsKey |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(false, this.region.containsKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(false, this.region.containsKey("key1")); |
| txMgrImpl.commit(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(false, this.region.containsKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(false, this.region.containsKey("key1")); |
| this.region.put("key1", "value3"); |
| assertEquals(true, this.region.containsKey("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try containsValueForKey |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(false, this.region.containsValueForKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(false, this.region.containsValueForKey("key1")); |
| txMgrImpl.commit(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| assertEquals(false, this.region.containsValueForKey("key1")); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(false, this.region.containsValueForKey("key1")); |
| this.region.put("key1", "value3"); |
| assertEquals(true, this.region.containsValueForKey("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| |
| // try an invalidate of an already invalid entry |
| this.region.remove("key1"); // non-tx |
| this.region.create("key1", null); // non-tx |
| txMgrImpl.begin(); |
| this.region.get("key1"); |
| this.region.localInvalidate("key1"); // should be a noop since it is already invalid |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| txMgrImpl.commit(); |
| assertEquals(false, this.region.containsKey("key1")); |
| |
| // make sure a noop invalidate is repeatable read |
| this.region.remove("key1"); // non-tx |
| this.region.create("key1", null); // non-tx |
| txMgrImpl.begin(); |
| this.region.localInvalidate("key1"); // should be a noop since it is already invalid |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(true, this.region.containsKey("key1")); |
| assertEquals(false, this.region.containsValueForKey("key1")); |
| txMgrImpl.commit(); |
| assertEquals(false, this.region.containsKey("key1")); |
| |
| // make sure a destroy that throws entryNotFound is repeatable read |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.begin(); |
| try { |
| this.region.localDestroy("key1"); |
| fail("expected EntryNotFoundException"); |
| } catch (EntryNotFoundException expected) { |
| } |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.create("key1", "value1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(false, this.region.containsKey("key1")); |
| txMgrImpl.commit(); |
| assertEquals(true, this.region.containsKey("key1")); |
| this.region.remove("key1"); // non-tx |
| |
| // make sure a create that throws entryExists is repeatable read |
| this.region.create("key1", "non-tx-value1"); // non-tx |
| txMgrImpl.begin(); |
| try { |
| this.region.create("key1", "value1"); |
| fail("expected EntryExistsException"); |
| } catch (EntryExistsException expected) { |
| } |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.remove("key1"); // non-tx |
| txMgrImpl.unpauseTransaction(tx); |
| assertEquals(true, this.region.containsKey("key1")); |
| txMgrImpl.commit(); |
| assertEquals(false, this.region.containsKey("key1")); |
| } |
| |
| @Test |
| public void testConflicts() throws CacheException { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| // try a put with no conflict to show that commit works |
| txMgrImpl.begin(); |
| this.region.put("key1", "value1"); |
| txMgrImpl.commit(); |
| assertEquals("value1", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // now try a put with a conflict and make sure it is detected |
| txMgrImpl.begin(); |
| this.region.put("key1", "value1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // slightly difference version where value already exists in cmt state |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.put("key1", "value1"); |
| txMgrImpl.commit(); |
| assertEquals("value1", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // now the conflict |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.put("key1", "value1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // now test create |
| txMgrImpl.begin(); |
| this.region.create("key1", "value1"); |
| txMgrImpl.commit(); |
| assertEquals("value1", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // now try a create with a conflict and make sure it is detected |
| txMgrImpl.begin(); |
| this.region.create("key1", "value1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // test localInvalidate |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.localInvalidate("key1"); |
| txMgrImpl.commit(); |
| assertTrue(this.region.containsKey("key1") && !this.region.containsValueForKey("key1")); |
| this.region.localDestroy("key1"); |
| |
| // now the conflict |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.localInvalidate("key1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // test invalidate |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.invalidate("key1"); |
| txMgrImpl.commit(); |
| assertTrue(this.region.containsKey("key1") && !this.region.containsValueForKey("key1")); |
| this.region.localDestroy("key1"); |
| |
| // now the conflict |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.invalidate("key1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // check C + DD is a NOOP that still gets conflict if non-tx entry created */ |
| this.txMgr.begin(); |
| this.region.create("newKey", "valueTX"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.create("newKey", "valueNONTX"); |
| txMgrImpl.unpauseTransaction(tx); |
| this.region.destroy("newKey"); |
| assertTrue(!this.region.containsKey("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("valueNONTX", this.region.get("newKey")); |
| this.region.localDestroy("newKey"); |
| |
| // check C + LD is a NOOP that still gets conflict if non-tx entry created */ |
| this.txMgr.begin(); |
| this.region.create("newKey", "valueTX"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.create("newKey", "valueNONTX"); |
| txMgrImpl.unpauseTransaction(tx); |
| this.region.localDestroy("newKey"); |
| assertTrue(!this.region.containsKey("key1")); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("valueNONTX", this.region.get("newKey")); |
| this.region.localDestroy("newKey"); |
| |
| // test localDestroy |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.localDestroy("key1"); |
| txMgrImpl.commit(); |
| assertTrue(!this.region.containsKey("key1")); |
| |
| // now the conflict |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.localDestroy("key1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| // test destroy |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.destroy("key1"); |
| txMgrImpl.commit(); |
| assertTrue(!this.region.containsKey("key1")); |
| |
| // now the conflict |
| this.region.put("key1", "value0"); |
| txMgrImpl.begin(); |
| this.region.destroy("key1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.put("key1", "value2"); // do a non-tx put to force conflict |
| txMgrImpl.unpauseTransaction(tx); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| assertEquals("value2", this.region.get("key1")); |
| this.region.localDestroy("key1"); |
| |
| checkUserAttributeConflict(txMgrImpl); |
| |
| // make sure non-tx local-invalidate followed by invalidate |
| // does not cause conflict |
| this.region.create("key1", "val1"); |
| this.region.localInvalidate("key1"); |
| txMgrImpl.begin(); |
| this.region.put("key1", "txVal1"); |
| tx = txMgrImpl.pauseTransaction(); |
| this.region.invalidate("key1"); |
| txMgrImpl.unpauseTransaction(tx); |
| txMgrImpl.commit(); |
| assertEquals("txVal1", this.region.getEntry("key1").getValue()); |
| this.region.destroy("key1"); |
| |
| // now try a put and a region destroy. |
| txMgrImpl.begin(); |
| this.region.create("key1", "value1"); |
| TXStateProxy tis = txMgrImpl.pauseTransaction(); |
| this.region.localDestroyRegion(); // non-tx |
| txMgrImpl.unpauseTransaction(tis); |
| |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (TransactionException ex) { |
| } |
| } |
| |
| protected void checkUserAttributeConflict(final CacheTransactionManager txMgrImpl) { |
| { // now check entry user attribute conflict checking |
| this.region.put("key1", "value0"); |
| Region.Entry cmtre = this.region.getEntry("key1"); |
| assertEquals(null, cmtre.getUserAttribute()); |
| txMgrImpl.begin(); |
| Region.Entry txre = this.region.getEntry("key1"); |
| txre.setUserAttribute("uaValue1"); |
| txMgrImpl.commit(); |
| assertEquals("uaValue1", cmtre.getUserAttribute()); |
| this.region.localDestroy("key1"); |
| |
| this.region.put("key1", "value0"); |
| cmtre = this.region.getEntry("key1"); |
| assertEquals("value0", cmtre.getValue()); |
| assertEquals(null, cmtre.getUserAttribute()); |
| this.txMgr.begin(); |
| txre = this.region.getEntry("key1"); |
| assertEquals("value0", txre.getValue()); |
| this.region.put("key1", "valueTX"); |
| assertEquals("valueTX", txre.getValue()); |
| assertEquals("value0", cmtre.getValue()); |
| assertEquals(null, txre.getUserAttribute()); |
| txre.setUserAttribute("uaValue1"); |
| assertEquals("uaValue1", txre.getUserAttribute()); |
| assertEquals(null, cmtre.getUserAttribute()); |
| cmtre.setUserAttribute("uaValue2"); |
| assertEquals("uaValue2", cmtre.getUserAttribute()); |
| assertEquals("uaValue1", txre.getUserAttribute()); |
| try { |
| txMgrImpl.commit(); |
| fail("expected CommitConflictException"); |
| } catch (CommitConflictException ex) { |
| } |
| try { |
| txre.getValue(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txre.isDestroyed(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txre.getUserAttribute(); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| try { |
| txre.setUserAttribute("foo"); |
| fail("expected IllegalStateException"); |
| } catch (IllegalStateException ok) { |
| } |
| assertEquals("uaValue2", cmtre.getUserAttribute()); |
| assertEquals("value0", cmtre.getValue()); |
| this.region.localDestroy("key1"); |
| } |
| } |
| |
| @Test |
| public void testNoopInvalidates() throws CacheException { |
| final CachePerfStats stats = this.cache.getCachePerfStats(); |
| TransactionListener tl = new TransactionListenerAdapter() { |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| te = event; |
| } |
| }; |
| this.txMgr.addListener(tl); |
| // Make sure invalidates done on invalid entries are noops |
| |
| { // distributed invalidate |
| // first make sure invalidate is counted as a change |
| int txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| assertEquals(1, te.getEvents().size()); |
| this.region.destroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.txMgr.commit(); |
| assertEquals(1, te.getEvents().size()); |
| this.region.destroy("key1"); |
| |
| // now make sure a committed entry that is invalid is not counted as a change |
| txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.region.invalidate("key1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(txRollbackChanges, stats.getTxRollbackChanges()); |
| assertEquals(0, te.getEvents().size()); |
| this.region.destroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.region.invalidate("key1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.txMgr.commit(); |
| assertEquals(0, te.getEvents().size()); |
| this.region.destroy("key1"); |
| |
| // now make sure that multiple invalidates of same entry are a single change |
| txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.region.invalidate("key1"); |
| this.region.invalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| assertEquals(1, te.getEvents().size()); |
| this.region.destroy("key1"); |
| |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.invalidate("key1"); |
| this.region.invalidate("key1"); |
| this.region.invalidate("key1"); |
| this.txMgr.commit(); |
| assertEquals(1, te.getEvents().size()); |
| this.region.destroy("key1"); |
| } |
| |
| { // local invalidate |
| // first make sure invalidate is counted as a change |
| int txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.localInvalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| this.region.destroy("key1"); |
| |
| // now make sure a committed entry that is invalid is not counted as a change |
| txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.region.localInvalidate("key1"); |
| this.txMgr.begin(); |
| this.region.localInvalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(txRollbackChanges, stats.getTxRollbackChanges()); |
| this.region.destroy("key1"); |
| |
| // now make sure that multiple localInvalidates of same entry are a single change |
| txRollbackChanges = stats.getTxRollbackChanges(); |
| this.region.create("key1", "value1"); |
| this.txMgr.begin(); |
| this.region.localInvalidate("key1"); |
| this.region.localInvalidate("key1"); |
| this.region.localInvalidate("key1"); |
| this.txMgr.rollback(); |
| assertEquals(txRollbackChanges + 1, stats.getTxRollbackChanges()); |
| this.region.destroy("key1"); |
| } |
| } |
| |
| private static void clearRegion(Region r) throws TimeoutException { |
| Iterator kI = r.keySet().iterator(); |
| try { |
| while (kI.hasNext()) { |
| r.destroy(kI.next()); |
| } |
| } catch (CacheException ce) { |
| fail("clearRegion operation failed"); |
| } |
| } |
| |
| private static final int LRUENTRY_NULL = 0; |
| private static final int LRUENTRY_STRING = 1; |
| private static final int LRUENTRY_INTEGER = 2; |
| private static final int LRUENTRY_LONG = 3; |
| private static final int LRUENTRY_DOUBLE = 4; |
| |
| private static void assertLRUEntries(Set entries, int size, String keyPrefix, int instanceId) { |
| assertEquals(size, entries.size()); |
| Iterator entItr = entries.iterator(); |
| while (entItr.hasNext()) { |
| Region.Entry re = (Region.Entry) entItr.next(); |
| switch (instanceId) { |
| case LRUENTRY_NULL: |
| assertNull(re.getValue()); |
| break; |
| case LRUENTRY_STRING: |
| assertTrue(re.getValue() instanceof String); |
| break; |
| case LRUENTRY_INTEGER: |
| assertTrue(re.getValue() instanceof Integer); |
| break; |
| case LRUENTRY_LONG: |
| assertTrue(re.getValue() instanceof Long); |
| break; |
| case LRUENTRY_DOUBLE: |
| assertTrue(re.getValue() instanceof Double); |
| break; |
| default: |
| fail("Unknown instance type in assertLRUEntries: " + instanceId); |
| } |
| String reKey = (String) re.getKey(); |
| assertTrue("expected " + reKey + " to start with " + keyPrefix, reKey.startsWith(keyPrefix)); |
| } |
| } |
| |
| @Test |
| public void testEviction() throws CacheException { |
| final int lruSize = 8; |
| AttributesFactory<String, Object> af = new AttributesFactory<>(); |
| af.setEvictionAttributes( |
| EvictionAttributes.createLRUEntryAttributes(lruSize, EvictionAction.LOCAL_DESTROY)); |
| af.setScope(Scope.LOCAL); |
| Region<String, Object> lruRegion = this.cache.createRegion(getUniqueName(), af.create()); |
| |
| // Non-TX LRU verification |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| int numToPut = lruSize + 2; |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| clearRegion(lruRegion); |
| |
| // TX LRU verification |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| numToPut = lruSize + 2; |
| this.txMgr.begin(); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Long(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| this.txMgr.commit(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_LONG); |
| clearRegion(lruRegion); |
| |
| // TX/non-TX no conflict verification w/ initial state |
| // full+2, all committed entries have TX refs |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| numToPut = lruSize + 2; |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.create("key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| this.txMgr.begin(); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Long(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| tx = txMgrImpl.pauseTransaction(); |
| |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("non-tx key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| assertNull(lruRegion.get("non-tx key0")); |
| |
| txMgrImpl.unpauseTransaction(tx); |
| this.txMgr.commit(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_LONG); |
| } |
| clearRegion(lruRegion); |
| |
| // TX/non-TX no conflict verification w/ invalid initial state |
| // full+2, all committed entries have TX refs using a loader |
| { |
| AttributesMutator<String, Object> mutator = lruRegion.getAttributesMutator(); |
| mutator.setCacheLoader(new CacheLoader() { |
| // int count = 0; |
| @Override |
| public Object load(LoaderHelper helper) throws CacheLoaderException { |
| return "value" + helper.getArgument(); |
| } |
| |
| @Override |
| public void close() {} |
| }); |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| numToPut = lruSize + 2; |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.create("key" + i, null); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_NULL); |
| // assertIndexDetailsEquals(lruSize, lruRegion.entrySet(false).size()); |
| this.txMgr.begin(); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.get("key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_STRING); |
| tx = txMgrImpl.pauseTransaction(); |
| |
| assertEquals(lruSize, lruRegion.entrySet(false).size()); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_NULL); |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.get("non-tx key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_NULL); |
| assertNull(lruRegion.getEntry("non-tx key0")); |
| |
| txMgrImpl.unpauseTransaction(tx); |
| this.txMgr.commit(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_STRING); |
| Iterator it = lruRegion.keySet().iterator(); |
| while (it.hasNext()) { |
| lruRegion.localInvalidate(it.next(), null); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_NULL); |
| mutator.setCacheLoader(null); |
| } |
| clearRegion(lruRegion); |
| |
| // TX/TX/non-TX no conflict verification w/ initial state full, TX |
| // add lruLimit+4, existing committed have TX 2 refs, force non-TX |
| // eviction, force TX eviction |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TransactionId txId1, txId2; |
| numToPut = lruSize + 4; |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| // Create entries |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.create("key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| this.txMgr.begin(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| // Add a TX reference to committed entries, add a few on top of that |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Long(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| txId1 = txMgrImpl.suspend(); |
| |
| this.txMgr.begin(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| // Add another TX reference to committed entries, add a few on top of that |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Double(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_DOUBLE); |
| txId2 = txMgrImpl.suspend(); |
| |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| // Force the Non-Tx "put" to remove each attempt since region is full |
| // and all the committed entries are currently part of a TX |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("non-tx key" + i, new Integer(i)); |
| } |
| assertTrue(numToPut > lruSize); |
| assertNull(lruRegion.get("non-tx key0")); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| txMgrImpl.resume(txId1); |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| // Check to make sure no conflict was caused by non-TX put evictions |
| // This should remove all references for each committed entry |
| this.txMgr.commit(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_LONG); |
| txMgrImpl.resume(txId2); |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_DOUBLE); |
| this.txMgr.rollback(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_LONG); |
| |
| // Test to make sure we can evict something that has been rolled back |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, "value" + i); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_STRING); |
| } |
| clearRegion(lruRegion); |
| |
| // TX/non-TX no conflict verification w/ initial state full, TX |
| // add lruLimit+4, force non-TX eviction, then rolls back, make |
| // sure that non-TX eviction works properly |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| numToPut = lruSize + 4; |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| // Create entries |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.create("key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| this.txMgr.begin(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| // Add a TX reference to committed entries, add a few on top of that |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Long(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| tx = txMgrImpl.pauseTransaction(); |
| |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| // Force the Non-Tx "put" to remove each attempt since region is full |
| // and all the committed entries are currently part of a TX |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("non-tx key" + i, new Integer(i)); |
| } |
| assertNull(lruRegion.get("non-tx key0")); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| txMgrImpl.unpauseTransaction(tx); |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| // This should remove all references for each committed entry |
| this.txMgr.rollback(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| // Test to make sure we can evict something that has been rolled back |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, "value" + i); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_STRING); |
| } |
| clearRegion(lruRegion); |
| |
| // TX/TX conflict with initial state full, TX |
| // add lruLimit+4, after failed commit make |
| // sure that non-TX eviction works properly |
| { |
| final TXManagerImpl txMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy tx; |
| numToPut = lruSize + 4; |
| assertEquals(0, lruRegion.entrySet(false).size()); |
| // Create entries |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.create("key" + i, new Integer(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| this.txMgr.begin(); |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| // Add a TX reference to committed entries, add a few on top of that |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, new Long(i)); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| tx = txMgrImpl.pauseTransaction(); |
| |
| // Cause a conflict |
| lruRegion.put("key" + (numToPut - 1), new Integer(numToPut - 1)); |
| |
| txMgrImpl.unpauseTransaction(tx); |
| assertLRUEntries(lruRegion.entrySet(false), numToPut, "key", LRUENTRY_LONG); |
| // This should remove all references for each committed entry |
| try { |
| this.txMgr.commit(); |
| fail("Expected CommitConflictException during commit LRU Eviction test!"); |
| } catch (CommitConflictException ok) { |
| } |
| |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_INTEGER); |
| |
| // Test to make sure we can evict something that has been rolled back |
| for (int i = 0; i < numToPut; ++i) { |
| lruRegion.put("key" + i, "value" + i); |
| } |
| assertLRUEntries(lruRegion.entrySet(false), lruSize, "key", LRUENTRY_STRING); |
| } |
| |
| lruRegion.localDestroyRegion(); |
| } |
| |
| @Test |
| public void testJTASynchronization() |
| throws CacheException, javax.transaction.NotSupportedException, |
| javax.transaction.RollbackException, javax.transaction.SystemException, |
| javax.transaction.HeuristicMixedException, javax.transaction.HeuristicRollbackException { |
| |
| javax.transaction.TransactionManager jtaTxMgr = this.cache.getJTATransactionManager(); |
| TransactionListener tl = new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| ++listenerAfterCommit; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| ++listenerAfterFailedCommit; |
| te = event; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| ++listenerAfterRollback; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| ++listenerClose; |
| } |
| }; |
| |
| this.txMgr.addListener(tl); |
| Synchronization gfTXSync; |
| |
| // Test successful JTA commit |
| jtaTxMgr.begin(); |
| this.txMgr.begin(); |
| { |
| TXManagerImpl gfTxMgrImpl = (TXManagerImpl) this.txMgr; |
| gfTXSync = gfTxMgrImpl.getTXState(); |
| } |
| jtaTxMgr.getTransaction().registerSynchronization(gfTXSync); |
| assertEquals(0, this.listenerAfterCommit); |
| this.cache.getLogger().info("SWAP:doingCreate"); |
| this.region.create("syncKey1", "syncVal1"); |
| jtaTxMgr.commit(); |
| assertEquals(1, this.listenerAfterCommit); |
| assertEquals("syncVal1", this.region.getEntry("syncKey1").getValue()); |
| |
| try { |
| this.txMgr.commit(); |
| fail("JTA Cache Manager should have called commit!"); |
| } catch (VirtualMachineError e) { |
| SystemFailure.initiateFailure(e); |
| throw e; |
| } catch (Throwable expected) { |
| } |
| |
| // Test JTA rollback |
| jtaTxMgr.begin(); |
| this.txMgr.begin(); |
| { |
| TXManagerImpl gfTxMgrImpl = (TXManagerImpl) this.txMgr; |
| gfTXSync = gfTxMgrImpl.getTXState(); |
| } |
| jtaTxMgr.getTransaction().registerSynchronization(gfTXSync); |
| assertEquals(0, this.listenerAfterRollback); |
| this.region.put("syncKey2", "syncVal2"); |
| jtaTxMgr.rollback(); |
| assertEquals(1, this.listenerAfterRollback); |
| assertTrue(!this.region.containsKey("syncKey2")); |
| |
| // Test failed JTA commit with suspend |
| jtaTxMgr.begin(); |
| this.txMgr.begin(); |
| { |
| TXManagerImpl gfTxMgrImpl = (TXManagerImpl) this.txMgr; |
| gfTXSync = gfTxMgrImpl.getTXState(); |
| jtaTxMgr.getTransaction().registerSynchronization(gfTXSync); |
| assertEquals(0, this.listenerAfterFailedCommit); |
| this.region.put("syncKey3", "syncVal3"); |
| assertEquals("syncVal3", this.region.getEntry("syncKey3").getValue()); |
| |
| TXStateProxy gfTx = gfTxMgrImpl.pauseTransaction(); |
| javax.transaction.Transaction jtaTx = jtaTxMgr.suspend(); |
| assertNull(jtaTxMgr.getTransaction()); |
| this.region.put("syncKey3", "syncVal4"); |
| assertEquals("syncVal4", this.region.getEntry("syncKey3").getValue()); |
| gfTxMgrImpl.unpauseTransaction(gfTx); |
| try { |
| jtaTxMgr.resume(jtaTx); |
| } catch (Exception failure) { |
| fail("JTA resume failed"); |
| } |
| assertNotNull(jtaTxMgr.getTransaction()); |
| } |
| assertEquals("syncVal3", this.region.getEntry("syncKey3").getValue()); |
| try { |
| jtaTxMgr.commit(); |
| fail("Expected JTA manager conflict exception!"); |
| } catch (VirtualMachineError e) { |
| SystemFailure.initiateFailure(e); |
| throw e; |
| } catch (Throwable expected) { |
| } |
| assertEquals(1, this.listenerAfterFailedCommit); |
| assertEquals("syncVal4", this.region.getEntry("syncKey3").getValue()); |
| |
| |
| // Test failed JTA commit with a new thread |
| jtaTxMgr.begin(); |
| this.txMgr.begin(); |
| { |
| TXManagerImpl gfTxMgrImpl = (TXManagerImpl) this.txMgr; |
| gfTXSync = gfTxMgrImpl.getTXState(); |
| jtaTxMgr.getTransaction().registerSynchronization(gfTXSync); |
| assertEquals(1, this.listenerAfterFailedCommit); |
| this.region.put("syncKey4", "syncVal3"); |
| assertEquals("syncVal3", this.region.getEntry("syncKey4").getValue()); |
| |
| // Create a new thread and have it update the same key, causing |
| // a conflict |
| final int signal[] = {0}; |
| Thread t = new Thread("non-TX conflict generator") { |
| @Override |
| public void run() { |
| try { |
| region.put("syncKey4", "syncVal4"); |
| while (true) |
| synchronized (signal) { |
| signal[0] = 1; |
| signal.notify(); |
| signal.wait(); |
| if (signal[0] == 0) { |
| break; |
| } |
| } |
| } catch (Exception error) { |
| fail("Non-tx thread failure due to: " + error); |
| } |
| } |
| }; |
| t.start(); |
| try { |
| while (true) |
| synchronized (signal) { |
| if (signal[0] == 1) { |
| signal[0] = 0; |
| signal.notify(); |
| break; |
| } else { |
| signal.wait(); |
| } |
| } |
| } catch (InterruptedException dangit) { |
| fail("Tx thread waiting for non-tx thread failed due to : " + dangit); |
| } |
| assertEquals("syncVal3", this.region.getEntry("syncKey4").getValue()); |
| } |
| try { |
| jtaTxMgr.commit(); |
| fail("Expected JTA manager conflict exception!"); |
| } catch (javax.transaction.HeuristicRollbackException expected) { |
| } catch (javax.transaction.RollbackException alsoExpected) { |
| } catch (VirtualMachineError e) { |
| SystemFailure.initiateFailure(e); |
| throw e; |
| } catch (Throwable yuk) { |
| fail("Did not expect this throwable from JTA commit: " + yuk); |
| } |
| assertEquals(2, this.listenerAfterFailedCommit); |
| assertEquals("syncVal4", this.region.getEntry("syncKey4").getValue()); |
| |
| this.txMgr.removeListener(tl); |
| } |
| |
| @Test |
| public void testJTAEnlistment() throws CacheException, javax.transaction.NotSupportedException, |
| javax.transaction.RollbackException, javax.transaction.SystemException, |
| javax.transaction.HeuristicMixedException, javax.transaction.HeuristicRollbackException { |
| |
| TransactionListener tl = new TransactionListener() { |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| ++listenerAfterCommit; |
| te = event; |
| } |
| |
| @Override |
| public void afterFailedCommit(TransactionEvent event) { |
| ++listenerAfterFailedCommit; |
| te = event; |
| } |
| |
| @Override |
| public void afterRollback(TransactionEvent event) { |
| ++listenerAfterRollback; |
| te = event; |
| } |
| |
| @Override |
| public void close() { |
| ++listenerClose; |
| } |
| }; |
| |
| this.txMgr.addListener(tl); |
| |
| javax.transaction.UserTransaction userTx = null; |
| try { |
| userTx = (javax.transaction.UserTransaction) this.cache.getJNDIContext() |
| .lookup("java:/UserTransaction"); |
| } catch (VirtualMachineError e) { |
| SystemFailure.initiateFailure(e); |
| throw e; |
| } catch (Throwable badDog) { |
| fail("Expected to get a healthy UserTransaction!"); |
| } |
| |
| // Test enlistment for put |
| // Test enlisted rollback |
| // Test prevention of rollback/commit for enlisted transaction |
| assertEquals(0, this.listenerAfterRollback); |
| userTx.begin(); |
| this.region.put("enlistKey", "enlistVal"); |
| assertEquals("enlistVal", this.region.getEntry("enlistKey").getValue()); |
| assertNotNull(this.txMgr.getTransactionId()); |
| try { |
| this.txMgr.rollback(); |
| fail("Should not allow a CacheTransactionManager.rollback call once the GF Tx is enlisted"); |
| } catch (VirtualMachineError e) { |
| SystemFailure.initiateFailure(e); |
| throw e; |
| } catch (Throwable ok) { |
| } |
| |
| try { |
| this.txMgr.commit(); |
| fail("Should not allow a CacheTransactionManager.commit() call once the GF Tx is enlisted"); |
| } catch (VirtualMachineError e) { |
| SystemFailure.initiateFailure(e); |
| throw e; |
| } catch (Throwable alsoOk) { |
| } |
| userTx.rollback(); |
| assertNull(this.txMgr.getTransactionId()); |
| assertTrue(!this.region.containsKey("enlistKey")); |
| assertEquals(1, this.listenerAfterRollback); |
| |
| // Test enlistment for create |
| // Test commit |
| assertEquals(0, this.listenerAfterCommit); |
| userTx.begin(); |
| this.region.create("enlistKey", "enlistVal"); |
| assertEquals("enlistVal", this.region.getEntry("enlistKey").getValue()); |
| assertNotNull(this.txMgr.getTransactionId()); |
| userTx.commit(); |
| assertNull(this.txMgr.getTransactionId()); |
| assertTrue(this.region.containsKey("enlistKey")); |
| assertEquals("enlistVal", this.region.getEntry("enlistKey").getValue()); |
| assertEquals(1, this.listenerAfterCommit); |
| |
| // Test enlistment for get |
| assertEquals(1, this.listenerAfterCommit); |
| userTx.begin(); |
| assertEquals("enlistVal", this.region.get("enlistKey")); |
| assertNotNull(this.txMgr.getTransactionId()); |
| userTx.commit(); |
| assertNull(this.txMgr.getTransactionId()); |
| assertEquals(2, this.listenerAfterCommit); |
| |
| // Test enlistment for invalidate |
| assertEquals(2, this.listenerAfterCommit); |
| userTx.begin(); |
| this.region.invalidate("enlistKey"); |
| assertTrue(this.region.containsKey("enlistKey")); |
| assertTrue(!this.region.containsValueForKey("enlistKey")); |
| assertNotNull(this.txMgr.getTransactionId()); |
| userTx.commit(); |
| assertNull(this.txMgr.getTransactionId()); |
| assertTrue(this.region.containsKey("enlistKey")); |
| assertTrue(!this.region.containsValueForKey("enlistKey")); |
| assertEquals(3, this.listenerAfterCommit); |
| |
| // Test enlistment for destroy |
| assertEquals(3, this.listenerAfterCommit); |
| userTx.begin(); |
| this.region.destroy("enlistKey"); |
| assertTrue(!this.region.containsKey("enlistKey")); |
| assertNotNull(this.txMgr.getTransactionId()); |
| userTx.commit(); |
| assertNull(this.txMgr.getTransactionId()); |
| assertTrue(!this.region.containsKey("enlistKey")); |
| assertEquals(4, this.listenerAfterCommit); |
| |
| // Test enlistment for load |
| AttributesMutator<String, String> mutator = this.region.getAttributesMutator(); |
| mutator.setCacheLoader(new CacheLoader<String, String>() { |
| int count = 0; |
| |
| @Override |
| public String load(LoaderHelper helper) throws CacheLoaderException { |
| return String.valueOf(count++); |
| } |
| |
| @Override |
| public void close() {} |
| }); |
| assertEquals(4, this.listenerAfterCommit); |
| userTx.begin(); |
| assertEquals("0", this.region.get("enlistKey")); |
| assertNotNull(this.txMgr.getTransactionId()); |
| userTx.commit(); |
| assertNull(this.txMgr.getTransactionId()); |
| assertTrue(this.region.containsKey("enlistKey")); |
| assertEquals("0", this.region.getEntry("enlistKey").getValue()); |
| assertEquals(5, this.listenerAfterCommit); |
| mutator.setCacheLoader(null); |
| |
| // Test enlisted failed commit |
| assertEquals(0, this.listenerAfterFailedCommit); |
| userTx.begin(); |
| this.region.put("enlistKey", "enlistVal"); |
| assertEquals("enlistVal", this.region.get("enlistKey")); |
| assertNotNull(this.txMgr.getTransactionId()); |
| { |
| TXManagerImpl gfTxMgrImpl = (TXManagerImpl) this.txMgr; |
| TXStateProxy gfTx = gfTxMgrImpl.pauseTransaction(); |
| |
| javax.transaction.TransactionManager jtaTxMgr = this.cache.getJTATransactionManager(); |
| javax.transaction.Transaction jtaTx = jtaTxMgr.suspend(); |
| |
| this.region.put("enlistKey", "conflictVal"); |
| assertEquals("conflictVal", this.region.get("enlistKey")); |
| |
| try { |
| jtaTxMgr.resume(jtaTx); |
| } catch (Exception failure) { |
| fail("JTA resume failed"); |
| } |
| gfTxMgrImpl.unpauseTransaction(gfTx); |
| } |
| assertEquals("enlistVal", this.region.get("enlistKey")); |
| try { |
| userTx.commit(); |
| fail("Expected JTA commit exception!"); |
| } catch (javax.transaction.HeuristicRollbackException expected) { |
| } catch (javax.transaction.RollbackException alsoExpected) { |
| } catch (Exception yuk) { |
| fail("Did not expect this exception from JTA commit: " + yuk); |
| } |
| assertNull(this.txMgr.getTransactionId()); |
| assertEquals("conflictVal", this.region.getEntry("enlistKey").getValue()); |
| assertEquals(1, this.listenerAfterFailedCommit); |
| |
| // Test rollbackOnly UserTransaction enlistment |
| userTx.begin(); |
| assertNull(this.txMgr.getTransactionId()); |
| userTx.setRollbackOnly(); |
| assertEquals(javax.transaction.Status.STATUS_MARKED_ROLLBACK, userTx.getStatus()); |
| try { |
| this.region.put("enlistKey", "enlistVal2"); |
| fail("Expected to get a FailedSynchronizationException!"); |
| } catch (FailedSynchronizationException okay) { |
| } |
| assertNull(this.txMgr.getTransactionId()); |
| try { |
| assertEquals("conflictVal", this.region.getEntry("enlistKey").getValue()); |
| fail("Expected to get a FailedSynchronizationException!"); |
| } catch (FailedSynchronizationException okay) { |
| } |
| assertTrue(!this.region.containsKey("enlistKey2")); |
| try { |
| this.region.put("enlistKey2", "enlistVal3"); |
| fail("Expected to get a FailedSynchronizationException!"); |
| } catch (FailedSynchronizationException okay) { |
| } |
| assertNull(this.txMgr.getTransactionId()); |
| try { |
| assertEquals("conflictVal", this.region.getEntry("enlistKey").getValue()); |
| fail("Expected to get a FailedSynchronizationException!"); |
| } catch (FailedSynchronizationException okay) { |
| } |
| assertTrue(!this.region.containsKey("enlistKey2")); |
| userTx.rollback(); |
| assertEquals("conflictVal", this.region.getEntry("enlistKey").getValue()); |
| assertTrue(!this.region.containsKey("enlistKey2")); |
| |
| this.txMgr.removeListener(tl); |
| } |
| |
| private static void waitForUpdates(final Index idx, final int expectedUpdates) { |
| // DistributedTestCase.WaitCriterion wc = new DistributedTestCase.WaitCriterion() { |
| // String excuse; |
| // public boolean done() { |
| // return idx.getStatistics().getNumUpdates() == expectedUpdates; |
| // } |
| // |
| // public String description() { |
| // return "expectedUpdates " + expectedUpdates + " but got this " |
| // + idx.getStatistics().getNumUpdates(); |
| // } |
| // }; |
| // DistributedTestCase.waitForCriterion(wc, 15 * 1000, 20, true); |
| |
| boolean done = false; |
| try { |
| for (StopWatch time = new StopWatch(true); !done |
| && time.elapsedTimeMillis() < 15 * 1000; done = |
| (idx.getStatistics().getNumUpdates() == expectedUpdates)) { |
| Thread.sleep(20); |
| } |
| } catch (InterruptedException e) { |
| Thread.currentThread().interrupt(); |
| } |
| assertTrue("expectedUpdates " + expectedUpdates + " but got this " |
| + idx.getStatistics().getNumUpdates(), done); |
| } |
| |
| private static void waitForKeys(final Index idx, final int expectedKeys) { |
| // DistributedTestCase.WaitCriterion wc = new DistributedTestCase.WaitCriterion() { |
| // String excuse; |
| // public boolean done() { |
| // return idx.getStatistics().getNumberOfKeys() == expectedKeys; |
| // } |
| // |
| // public String description() { |
| // return "expectedKeys " + expectedKeys + " but got this " |
| // + idx.getStatistics().getNumberOfKeys(); |
| // } |
| // }; |
| // DistributedTestCase.waitForCriterion(wc, 15 * 1000, 20, true); |
| |
| boolean done = false; |
| try { |
| for (StopWatch time = new StopWatch(true); !done |
| && time.elapsedTimeMillis() < 15 * 1000; done = |
| (idx.getStatistics().getNumberOfKeys() == expectedKeys)) { |
| Thread.sleep(20); |
| } |
| } catch (InterruptedException e) { |
| Thread.currentThread().interrupt(); |
| } |
| assertTrue( |
| "expectedKeys " + expectedKeys + " but got this " + idx.getStatistics().getNumberOfKeys(), |
| done); |
| } |
| |
| @Test |
| public void testTXAndQueries() throws CacheException, QueryException { |
| IndexManager.TEST_RANGEINDEX_ONLY = true; |
| try { |
| final QueryService qs = this.cache.getQueryService(); |
| |
| final String fromClause = this.region.getFullPath() + " value "; |
| final String qstr = "SELECT DISTINCT * FROM " + fromClause; |
| |
| // Create a region with async index updates |
| AttributesFactory af = new AttributesFactory(this.region.getAttributes()); |
| af.setIndexMaintenanceSynchronous(false); |
| final Region aIregion = this.cache.createRegion(getUniqueName(), af.create()); |
| final String aIfromClause = aIregion.getFullPath() + " value "; |
| final String aIqstr = "SELECT DISTINCT * FROM " + aIfromClause; |
| |
| // Confirm base functionality for query results |
| this.region.put("qkey0", "qval0"); |
| this.region.put("qkey1", "qval01"); |
| Query q = qs.newQuery(qstr); |
| SelectResults res = (SelectResults) q.execute(); |
| assertEquals(2, res.size()); |
| String val; |
| for (Iterator resI = res.iterator(); resI.hasNext();) { |
| val = (String) resI.next(); |
| assertTrue("Value: " + val + " does not start with qval", val.startsWith("qval")); |
| } |
| q = qs.newQuery(qstr + " where value.length > 6"); |
| res = (SelectResults) q.execute(); |
| assertEquals(0, res.size()); |
| |
| aIregion.put("qkey0", "qval0"); |
| aIregion.put("qkey1", "qval01"); |
| q = qs.newQuery(aIqstr); |
| res = (SelectResults) q.execute(); |
| assertEquals(2, res.size()); |
| for (Iterator resI = res.iterator(); resI.hasNext();) { |
| val = (String) resI.next(); |
| assertTrue("Value: " + val + " does not start with qval", val.startsWith("qval")); |
| } |
| q = qs.newQuery(qstr + " where value.length > 6"); |
| res = (SelectResults) q.execute(); |
| assertEquals(0, res.size()); |
| |
| // Test query results in a transaction |
| this.txMgr.begin(); |
| Query q1 = qs.newQuery(qstr); |
| this.region.put("noQkey2", "noQval2"); |
| res = (SelectResults) q1.execute(); |
| assertEquals(2, res.size()); |
| for (Iterator resI = res.iterator(); resI.hasNext();) { |
| val = (String) resI.next(); |
| assertTrue("Value: " + val + " does not start with qval", val.startsWith("qval")); |
| } |
| Query aIq1 = qs.newQuery(aIqstr); |
| aIregion.put("noQkey2", "noQval2"); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(2, res.size()); |
| for (Iterator resI = res.iterator(); resI.hasNext();) { |
| val = (String) resI.next(); |
| assertTrue("Value: " + val + " does not start with qval", val.startsWith("qval")); |
| } |
| Query q2 = qs.newQuery(qstr + " where value.length > 6"); |
| res = (SelectResults) q2.execute(); |
| assertEquals(0, res.size()); |
| Query aIq2 = qs.newQuery(aIqstr + " where value.length > 6"); |
| res = (SelectResults) aIq2.execute(); |
| assertEquals(0, res.size()); |
| this.txMgr.commit(); |
| res = (SelectResults) q1.execute(); |
| assertEquals(3, res.size()); |
| res = (SelectResults) q2.execute(); |
| assertEquals(1, res.size()); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(3, res.size()); |
| res = (SelectResults) aIq2.execute(); |
| assertEquals(1, res.size()); |
| |
| this.region.destroy("noQkey2"); |
| aIregion.destroy("noQkey2"); |
| |
| // Confirm base functionality for index creation |
| Index index0 = qs.createIndex("TXIndex0", IndexType.FUNCTIONAL, "value.length", fromClause); |
| assertEquals(2, index0.getStatistics().getNumberOfKeys()); |
| assertEquals(2, index0.getStatistics().getNumberOfValues()); |
| assertEquals(2, index0.getStatistics().getNumUpdates()); // Shouldn't this be zero? |
| Index aIindex0 = |
| qs.createIndex("aITXIndex0", IndexType.FUNCTIONAL, "value.length", aIfromClause); |
| assertEquals(2, aIindex0.getStatistics().getNumberOfKeys()); |
| assertEquals(2, aIindex0.getStatistics().getNumberOfValues()); |
| assertEquals(2, aIindex0.getStatistics().getNumUpdates()); // Shouldn't this be zero? |
| q = qs.newQuery(qstr); |
| res = (SelectResults) q.execute(); |
| assertEquals(2, res.size()); |
| assertEquals(0, index0.getStatistics().getTotalUses()); |
| aIq1 = qs.newQuery(aIqstr); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(2, res.size()); |
| assertEquals(0, aIindex0.getStatistics().getTotalUses()); |
| |
| final String val2 = "qval000002"; |
| this.region.put("qkey2", val2); |
| assertEquals(3, index0.getStatistics().getNumUpdates()); // Shouldn't this be 1? |
| assertEquals(3, index0.getStatistics().getNumberOfKeys()); |
| assertEquals(3, index0.getStatistics().getNumberOfValues()); |
| aIregion.put("qkey2", val2); |
| final IndexManager.IndexUpdaterThread upThread = |
| ((AbstractRegion) aIregion).getIndexManager().getUpdaterThread(); |
| while (!upThread.isDone()) { |
| pause(20); |
| } |
| // @todo asif: for some reason the value returned by getNumberOfKeys is unstable. |
| // Even when the code waits for it to be the expected value it intermittently |
| // will fail because it never gets to be the expected value. |
| // This stat (in RangeIndex at least) is only updated when we add a new key |
| // to the valueToEntriesMap. I do not see a place that we ever remove from |
| // this map (even when we do a removeMapping). |
| waitForUpdates(aIindex0, 3); |
| waitForKeys(aIindex0, 3); |
| assertEquals(3, aIindex0.getStatistics().getNumUpdates()); // Shouldn't this be 1? |
| assertEquals(3, aIindex0.getStatistics().getNumberOfKeys()); |
| assertEquals(3, aIindex0.getStatistics().getNumberOfValues()); |
| q = qs.newQuery("ELEMENT(" + qstr + " where value.length > 6)"); |
| assertEquals(val2, (String) q.execute()); |
| assertEquals(1, index0.getStatistics().getTotalUses()); |
| aIq1 = qs.newQuery("ELEMENT(" + aIqstr + " where value.length > 6)"); |
| assertEquals(val2, (String) aIq1.execute()); |
| |
| this.region.destroy("qkey2"); |
| waitForKeys(index0, 2); |
| assertEquals(2, index0.getStatistics().getNumberOfKeys()); // Shouldn't this be 1, again? |
| assertEquals(2, index0.getStatistics().getNumberOfValues()); |
| assertEquals(4, index0.getStatistics().getNumUpdates()); |
| aIregion.destroy("qkey2"); |
| while (!upThread.isDone()) { |
| pause(20); |
| } |
| waitForUpdates(aIindex0, 4); |
| // waitForKeys(aIindex0, 3); |
| // assertIndexDetailsEquals(3, aIindex0.getStatistics().getNumberOfKeys()); // Shouldn't this |
| // be 1, again? |
| assertEquals(2, aIindex0.getStatistics().getNumberOfValues()); |
| assertEquals(4, aIindex0.getStatistics().getNumUpdates()); |
| |
| // Test index creation |
| this.txMgr.begin(); |
| this.region.destroy("qkey1"); |
| this.region.put("noQkey3", "noQval3"); |
| Index index1 = qs.createIndex("TXIndex1", IndexType.FUNCTIONAL, "value", fromClause); |
| assertEquals(2, index1.getStatistics().getNumberOfKeys()); |
| assertEquals(2, index1.getStatistics().getNumberOfValues()); |
| assertEquals(2, index1.getStatistics().getNumUpdates()); |
| assertEquals(2, index0.getStatistics().getNumberOfKeys()); |
| assertEquals(2, index0.getStatistics().getNumberOfValues()); |
| assertEquals(4, index0.getStatistics().getNumUpdates()); |
| |
| aIregion.destroy("qkey1"); |
| aIregion.put("noQkey3", "noQval3"); |
| Index aIindex1 = qs.createIndex("aITXIndex1", IndexType.FUNCTIONAL, "value", aIfromClause); |
| while (!upThread.isDone()) { |
| pause(20); |
| } |
| waitForUpdates(aIindex0, 4); |
| waitForUpdates(aIindex1, 2); |
| // waitForKeys(aIindex0, 3); |
| // waitForKeys(aIindex1, 2); |
| assertEquals(2, aIindex1.getStatistics().getNumberOfKeys()); |
| assertEquals(2, aIindex1.getStatistics().getNumberOfValues()); |
| assertEquals(2, aIindex1.getStatistics().getNumUpdates()); |
| // assertIndexDetailsEquals(3, aIindex0.getStatistics().getNumberOfKeys()); |
| assertEquals(2, aIindex0.getStatistics().getNumberOfValues()); |
| assertEquals(4, aIindex0.getStatistics().getNumUpdates()); |
| |
| |
| q = qs.newQuery(qstr); |
| res = (SelectResults) q.execute(); |
| assertEquals(2, res.size()); |
| assertEquals(0, index1.getStatistics().getTotalUses()); |
| assertEquals(1, index0.getStatistics().getTotalUses()); |
| |
| aIq1 = qs.newQuery(aIqstr); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(2, res.size()); |
| assertEquals(0, aIindex1.getStatistics().getTotalUses()); |
| assertEquals(1, aIindex0.getStatistics().getTotalUses()); |
| |
| q = qs.newQuery(qstr + " where value < 'q'"); |
| res = (SelectResults) q.execute(); |
| assertEquals(1, index1.getStatistics().getTotalUses()); |
| assertEquals(0, res.size()); |
| |
| aIq1 = qs.newQuery(aIqstr + " where value < 'q'"); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(1, aIindex1.getStatistics().getTotalUses()); |
| assertEquals(0, res.size()); |
| |
| this.region.put("noQkey4", "noQval4"); |
| assertEquals(2, index1.getStatistics().getNumberOfKeys()); |
| assertEquals(2, index1.getStatistics().getNumberOfValues()); |
| assertEquals(2, index1.getStatistics().getNumUpdates()); |
| assertEquals(2, index0.getStatistics().getNumberOfKeys()); |
| assertEquals(2, index0.getStatistics().getNumberOfValues()); |
| assertEquals(4, index0.getStatistics().getNumUpdates()); |
| |
| aIregion.put("noQkey4", "noQval4"); |
| while (!upThread.isDone()) { |
| pause(20); |
| } |
| waitForUpdates(aIindex0, 4); |
| waitForUpdates(aIindex1, 2); |
| waitForKeys(aIindex0, 2); |
| // waitForKeys(aIindex1, 2); |
| // assertIndexDetailsEquals(2, aIindex1.getStatistics().getNumberOfKeys()); |
| assertEquals(2, aIindex1.getStatistics().getNumberOfValues()); |
| assertEquals(2, aIindex1.getStatistics().getNumUpdates()); |
| assertEquals(2, aIindex0.getStatistics().getNumberOfKeys()); |
| assertEquals(2, aIindex0.getStatistics().getNumberOfValues()); |
| assertEquals(4, aIindex0.getStatistics().getNumUpdates()); |
| |
| q = qs.newQuery(qstr + " where value < 'q'"); |
| res = (SelectResults) q.execute(); |
| assertEquals(2, index1.getStatistics().getTotalUses()); |
| assertEquals(0, res.size()); |
| |
| aIq1 = qs.newQuery(aIqstr + " where value <'q'"); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(2, aIindex1.getStatistics().getTotalUses()); |
| assertEquals(0, res.size()); |
| |
| q = qs.newQuery(qstr + " where value.length > 6"); |
| res = (SelectResults) q.execute(); |
| assertEquals(2, index0.getStatistics().getTotalUses()); |
| assertEquals(0, res.size()); |
| |
| aIq1 = qs.newQuery(aIqstr + " where value.length > 6"); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(2, aIindex0.getStatistics().getTotalUses()); |
| assertEquals(0, res.size()); |
| |
| this.txMgr.commit(); |
| assertEquals(3, index1.getStatistics().getNumberOfKeys()); |
| assertEquals(3, index1.getStatistics().getNumberOfValues()); // Shouldn't this be 4? |
| assertEquals(5, index1.getStatistics().getNumUpdates()); |
| assertEquals(2, index0.getStatistics().getNumberOfKeys()); |
| assertEquals(3, index0.getStatistics().getNumberOfValues()); // Shouldn't this be 4? |
| assertEquals(7, index0.getStatistics().getNumUpdates()); |
| |
| while (!upThread.isDone()) { |
| pause(20); |
| } |
| waitForUpdates(aIindex0, 7); |
| waitForUpdates(aIindex1, 5); |
| // waitForKeys(aIindex0, 4); // sometimes 3 sometimes 4 |
| // waitForKeys(aIindex1, 3); |
| assertEquals(3, aIindex1.getStatistics().getNumberOfKeys()); |
| assertEquals(3, aIindex1.getStatistics().getNumberOfValues()); // Shouldn't this be 4? |
| assertEquals(5, aIindex1.getStatistics().getNumUpdates()); |
| // assertIndexDetailsEquals(4, aIindex0.getStatistics().getNumberOfKeys()); |
| assertEquals(3, aIindex0.getStatistics().getNumberOfValues()); // Shouldn't this be 4? |
| assertEquals(7, aIindex0.getStatistics().getNumUpdates()); |
| |
| q = qs.newQuery(qstr + " where value <'q'"); |
| res = (SelectResults) q.execute(); |
| assertEquals(3, index1.getStatistics().getTotalUses()); |
| assertEquals(2, res.size()); |
| |
| aIq1 = qs.newQuery(aIqstr + " where value < 'q'"); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(3, aIindex1.getStatistics().getTotalUses()); |
| assertEquals(2, res.size()); |
| |
| q = qs.newQuery(qstr + " where value.length > 6"); |
| res = (SelectResults) q.execute(); |
| assertEquals(3, index0.getStatistics().getTotalUses()); |
| assertEquals(2, res.size()); |
| |
| aIq1 = qs.newQuery(aIqstr + " where value.length > 6"); |
| res = (SelectResults) aIq1.execute(); |
| assertEquals(3, aIindex0.getStatistics().getTotalUses()); |
| assertEquals(2, res.size()); |
| } finally { |
| IndexManager.TEST_RANGEINDEX_ONLY = false; |
| } |
| } |
| |
| /** |
| * make sure that we do not expose BucketRegion on transactionListener events |
| * |
| */ |
| @Test |
| public void testInternalRegionNotExposed() throws Exception { |
| TransactionListenerForRegionTest tl = new TransactionListenerForRegionTest(); |
| CacheTransactionManager ctm = this.cache.getCacheTransactionManager(); |
| ctm.addListener(tl); |
| CacheListenerForRegionTest cl = new CacheListenerForRegionTest(); |
| AttributesFactory af = new AttributesFactory(); |
| PartitionAttributes pa = |
| new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(1).create(); |
| af.setPartitionAttributes(pa); |
| af.addCacheListener(cl); |
| Region pr = this.cache.createRegion("testTxEventForRegion", af.create()); |
| pr.put(2, "tw"); |
| pr.put(3, "three"); |
| pr.put(4, "four"); |
| ctm.begin(); |
| pr.put(1, "one"); |
| pr.put(2, "two"); |
| pr.invalidate(3); |
| pr.destroy(4); |
| ctm.commit(); |
| assertFalse(tl.exceptionOccurred); |
| assertFalse(cl.exceptionOccurred); |
| } |
| |
| |
| |
| /** |
| * make sure that we throw an UnsupportedOperationInTransactionException |
| * |
| */ |
| @Test |
| public void testPutAllSupported() throws Exception { |
| TXManagerImpl ctm = this.cache.getTxManager(); |
| AttributesFactory af = new AttributesFactory(); |
| Region r = this.cache.createRegion("dRegion", af.create()); |
| PartitionAttributes pa = |
| new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(1).create(); |
| af.setPartitionAttributes(pa); |
| Region pr = this.cache.createRegion("prRegion", af.create()); |
| Map map = new HashMap(); |
| map.put("stuff", "junk"); |
| map.put("stuff2", "junk2"); |
| ctm.begin(); |
| pr.putAll(map); |
| r.putAll(map); |
| TXStateProxy tx = ctm.pauseTransaction(); |
| assertTrue(!pr.containsKey("stuff")); |
| assertTrue(!r.containsKey("stuff")); |
| ctm.unpauseTransaction(tx); |
| ctm.commit(); |
| assertTrue(pr.containsKey("stuff")); |
| assertTrue(r.containsKey("stuff")); |
| } |
| |
| |
| /** |
| * make sure that we throw an UnsupportedOperationInTransactionException |
| * |
| */ |
| @Test |
| public void testGetAllSupported() throws Exception { |
| CacheTransactionManager ctm = this.cache.getCacheTransactionManager(); |
| AttributesFactory af = new AttributesFactory(); |
| Region r = this.cache.createRegion("dRegion", af.create()); |
| PartitionAttributes pa = |
| new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(1).create(); |
| af.setPartitionAttributes(pa); |
| Region pr = this.cache.createRegion("prRegion", af.create()); |
| List list = new ArrayList(); |
| list.add("stuff"); |
| list.add("stuff2"); |
| ctm.begin(); |
| pr.getAll(list); |
| r.getAll(list); |
| ctm.commit(); |
| // now we aren't in tx so these shouldn't throw |
| pr.getAll(list); |
| r.getAll(list); |
| } |
| |
| |
| |
| /** |
| * make sure that we throw an UnsupportedOperationInTransactionException |
| * |
| */ |
| @Test |
| public void testDestroyRegionNotSupported() throws Exception { |
| CacheTransactionManager ctm = this.cache.getCacheTransactionManager(); |
| AttributesFactory af = new AttributesFactory(); |
| Region r = this.cache.createRegion("dRegion", af.create()); |
| PartitionAttributes pa = |
| new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(1).create(); |
| af.setPartitionAttributes(pa); |
| Region pr = this.cache.createRegion("prRegion", af.create()); |
| List list = new ArrayList(); |
| list.add("stuff"); |
| list.add("stuff2"); |
| ctm.begin(); |
| try { |
| pr.destroyRegion(); |
| fail("Should have thrown UnsupportedOperationInTransactionException during destroyRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| try { |
| pr.localDestroyRegion(); |
| fail( |
| "Should have thrown UnsupportedOperationInTransactionException during localDestroyRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| try { |
| r.destroyRegion(); |
| fail("Should have thrown UnsupportedOperationInTransactionException during destroyRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| |
| try { |
| r.localDestroyRegion(); |
| fail( |
| "Should have thrown UnsupportedOperationInTransactionException during localDestroyRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| assertTrue(!pr.isDestroyed()); |
| assertTrue(!r.isDestroyed()); |
| |
| ctm.commit(); |
| // now we aren't in tx so these shouldn't throw |
| pr.destroyRegion(); |
| r.destroyRegion(); |
| |
| } |
| |
| /** |
| * make sure that we throw an UnsupportedOperationInTransactionException |
| * |
| */ |
| @Test |
| public void testInvalidateRegionNotSupported() throws Exception { |
| CacheTransactionManager ctm = this.cache.getCacheTransactionManager(); |
| AttributesFactory af = new AttributesFactory(); |
| Region r = this.cache.createRegion("dRegion", af.create()); |
| PartitionAttributes pa = |
| new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(1).create(); |
| af.setPartitionAttributes(pa); |
| Region pr = this.cache.createRegion("prRegion", af.create()); |
| ctm.begin(); |
| try { |
| pr.invalidateRegion(); |
| fail("Should have thrown UnsupportedOperationInTransactionException during invalidateRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| try { |
| pr.localInvalidateRegion(); |
| fail( |
| "Should have thrown UnsupportedOperationInTransactionException during localInvalidateRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| try { |
| r.invalidateRegion(); |
| fail("Should have thrown UnsupportedOperationInTransactionException during invalidateRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| |
| try { |
| r.localInvalidateRegion(); |
| fail( |
| "Should have thrown UnsupportedOperationInTransactionException during localInvalidateRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| ctm.commit(); |
| // now we aren't in tx so these shouldn't throw |
| pr.invalidateRegion(); |
| r.invalidateRegion(); |
| |
| } |
| |
| /** |
| * make sure that we throw an UnsupportedOperationInTransactionException |
| * |
| */ |
| @Test |
| public void testClearRegionNotSupported() throws Exception { |
| CacheTransactionManager ctm = this.cache.getCacheTransactionManager(); |
| AttributesFactory af = new AttributesFactory(); |
| Region r = this.cache.createRegion("dRegion", af.create()); |
| PartitionAttributes pa = |
| new PartitionAttributesFactory().setRedundantCopies(0).setTotalNumBuckets(1).create(); |
| af.setPartitionAttributes(pa); |
| Region pr = this.cache.createRegion("prRegion", af.create()); |
| ctm.begin(); |
| try { |
| pr.clear(); |
| fail("Should have thrown UnsupportedOperation during invalidateRegion"); |
| } catch (UnsupportedOperationException ee) { |
| // expected |
| } |
| try { |
| pr.localClear(); |
| fail("Should have thrown UnsupportedOperation during localInvalidateRegion"); |
| } catch (UnsupportedOperationException ee) { |
| // expected |
| } |
| try { |
| r.clear(); |
| fail("Should have thrown UnsupportedOperationInTransactionException during invalidateRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| |
| try { |
| r.localClear(); |
| fail( |
| "Should have thrown UnsupportedOperationInTransactionException during localInvalidateRegion"); |
| } catch (UnsupportedOperationInTransactionException ee) { |
| // expected |
| } |
| ctm.commit(); |
| // now we aren't in tx so these shouldn't throw |
| pr.invalidateRegion(); |
| r.invalidateRegion(); |
| |
| } |
| |
| @Test |
| public void testBug51781() { |
| AttributesFactory<Integer, String> af = new AttributesFactory<Integer, String>(); |
| af.setDataPolicy(DataPolicy.NORMAL); |
| Region<Integer, String> r = this.cache.createRegion(getUniqueName(), af.create()); |
| CacheTransactionManager mgr = this.cache.getCacheTransactionManager(); |
| r.put(1, "value1"); |
| r.put(2, "value2"); |
| assertEquals(2, r.size()); |
| mgr.begin(); |
| r.put(3, "value3"); |
| r.destroy(3); |
| mgr.commit(); |
| assertEquals(2, r.size()); |
| } |
| |
| private String getUniqueName() { |
| return getClass().getSimpleName() + "_" + testName.getMethodName(); |
| } |
| |
| private static class TransactionListenerForRegionTest extends TransactionListenerAdapter { |
| private boolean exceptionOccurred = false; |
| |
| @Override |
| public void afterCommit(TransactionEvent event) { |
| List<CacheEvent<?, ?>> events = event.getEvents(); |
| for (CacheEvent<?, ?> e : events) { |
| if (!(SEPARATOR + "testTxEventForRegion").equals(e.getRegion().getFullPath())) { |
| exceptionOccurred = true; |
| } |
| } |
| } |
| } |
| |
| private static class CacheListenerForRegionTest extends CacheListenerAdapter { |
| private boolean exceptionOccurred = false; |
| |
| @Override |
| public void afterCreate(EntryEvent event) { |
| verifyRegion(event); |
| } |
| |
| @Override |
| public void afterUpdate(EntryEvent event) { |
| verifyRegion(event); |
| } |
| |
| private void verifyRegion(EntryEvent event) { |
| if (!(SEPARATOR + "testTxEventForRegion").equals(event.getRegion().getFullPath())) { |
| exceptionOccurred = true; |
| } |
| } |
| } |
| |
| private void verifyEventProps(EntryEvent ev) { |
| assertTrue(!ev.getOperation().isLocalLoad()); |
| assertTrue(!ev.getOperation().isNetLoad()); |
| assertTrue(!ev.getOperation().isLoad()); |
| assertTrue(!ev.getOperation().isNetSearch()); |
| } |
| |
| private enum OperationType { |
| REPLACE, REMOVE |
| } |
| |
| @Test |
| public void removeShouldNotCleanupRepeatableReadTXEntriesIfEntryNotFound() { |
| repeatableReadTXEntriesShouldNotBeCleanedUpIfEntryNotFound(OperationType.REMOVE); |
| } |
| |
| @Test |
| public void replaceShouldNotCleanupRepeatableReadTXEntriesIfEntryNotFound() { |
| repeatableReadTXEntriesShouldNotBeCleanedUpIfEntryNotFound(OperationType.REPLACE); |
| } |
| |
| private void repeatableReadTXEntriesShouldNotBeCleanedUpIfEntryNotFound(OperationType type) { |
| RegionFactory regionFactory = cache.createRegionFactory(RegionShortcut.REPLICATE); |
| Region<Integer, String> region = regionFactory.create(getUniqueName()); |
| region.put(1, "value1"); |
| region.put(2, "value2"); |
| txMgr.begin(); |
| region.put(1, "newValue1"); |
| TransactionId transaction1 = txMgr.suspend(); |
| |
| txMgr.begin(); |
| region.get(1); // a repeatable read operation |
| switch (type) { |
| case REMOVE: |
| assertThat(region.remove(2, "nonExistingValue")).isFalse(); |
| break; |
| case REPLACE: |
| assertThat(region.replace(2, "newValue", "nonExistingValue")).isFalse(); |
| break; |
| default: |
| throw new RuntimeException("Unknown operation"); |
| }; |
| TransactionId transaction2 = txMgr.suspend(); |
| |
| txMgr.resume(transaction1); |
| txMgr.commit(); |
| |
| txMgr.resume(transaction2); |
| region.put(1, "anotherValue"); |
| assertThatThrownBy(() -> txMgr.commit()).isInstanceOf(CommitConflictException.class); |
| } |
| |
| } |