/*
* Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved.
*
* Licensed 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 com.hazelcast.core;
import com.hazelcast.query.EntryObject;
import com.hazelcast.query.Predicate;
import com.hazelcast.query.PredicateBuilder;
import com.hazelcast.util.ResponseQueueFactory;
import org.junit.*;
import org.junit.runner.RunWith;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
@RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class)
public class TransactionTest {
@BeforeClass
public static void init() throws Exception {
Hazelcast.shutdownAll();
}
@Test
public void testMapGetSimple() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapGetSimple");
txnMap.put("1", "value");
txnMap.begin();
assertEquals("value", txnMap.get("1"));
assertEquals("value", txnMap.get("1"));
assertEquals("value", txnMap.get("1"));
assertEquals(1, txnMap.size());
txnMap.commit();
assertEquals(1, txnMap.size());
}
@Test
public void testMapPutSimple() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapPutSimple");
txnMap.begin();
txnMap.put("1", "value");
assertEquals(1, txnMap.size());
txnMap.commit();
assertEquals(1, txnMap.size());
}
@Test
public void testMapPutAndGetSimple() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapPutAndGetSimple");
txnMap.put("1", "value");
txnMap.begin();
assertEquals("value", txnMap.get("1"));
assertEquals("value", txnMap.get("1"));
assertEquals("value", txnMap.put("1", "value2"));
assertEquals("value2", txnMap.put("1", "value3"));
assertEquals("value3", txnMap.get("1"));
assertEquals(1, txnMap.size());
txnMap.commit();
assertEquals(1, txnMap.size());
}
@Test
public void testMapContainsKey() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapContainsKey");
txnMap.put("1", "value");
Assert.assertTrue(txnMap.containsKey("1"));
txnMap.begin();
Assert.assertTrue(txnMap.containsKey("1"));
assertEquals("value", txnMap.get("1"));
Assert.assertTrue(txnMap.containsKey("1"));
txnMap.commit();
Assert.assertTrue(txnMap.containsKey("1"));
assertEquals(1, txnMap.size());
}
@Test
public void testMapContainsValue() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapContainsValue");
txnMap.put("1", "value");
txnMap.put("2", "value");
Assert.assertTrue(txnMap.containsValue("value"));
txnMap.begin();
Assert.assertTrue(txnMap.containsValue("value"));
txnMap.commit();
assertEquals(2, txnMap.size());
}
@Test
public void testMultiMapContainsEntry() {
TransactionalMultiMap txnMap = newTransactionalMultiMapProxy("testMultiMapContainsEntry");
txnMap.put("1", "value");
Assert.assertTrue(txnMap.containsEntry("1", "value"));
txnMap.begin();
txnMap.put("1", "value2");
Assert.assertTrue(txnMap.containsEntry("1", "value"));
Assert.assertTrue(txnMap.containsEntry("1", "value2"));
txnMap.remove("1", "value2");
Assert.assertTrue(txnMap.containsEntry("1", "value"));
Assert.assertFalse(txnMap.containsEntry("1", "value2"));
txnMap.commit();
Assert.assertTrue(txnMap.containsEntry("1", "value"));
assertEquals(1, txnMap.size());
}
@Test
public void testMapIterateEntries() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapIterateEntries");
txnMap.put("1", "value1");
assertEquals(1, txnMap.size());
txnMap.begin();
txnMap.put("2", "value2");
assertEquals(2, txnMap.size());
Set<Map.Entry> entries = txnMap.entrySet();
for (Map.Entry entry : entries) {
if ("1".equals(entry.getKey())) {
assertEquals("value1", entry.getValue());
} else if ("2".equals(entry.getKey())) {
assertEquals("value2", entry.getValue());
} else throw new RuntimeException("cannot contain another entry with key " + entry.getKey());
}
txnMap.commit();
assertEquals(2, txnMap.size());
}
@Test
public void testMapIterateEntries2() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapIterateEntries2");
assertEquals(0, txnMap.size());
txnMap.begin();
txnMap.put("1", "value1");
txnMap.put("2", "value2");
assertEquals(2, txnMap.size());
Set<Map.Entry> entries = txnMap.entrySet();
for (Map.Entry entry : entries) {
if ("1".equals(entry.getKey())) {
assertEquals("value1", entry.getValue());
} else if ("2".equals(entry.getKey())) {
assertEquals("value2", entry.getValue());
} else throw new RuntimeException("cannot contain another entry with key " + entry.getKey());
}
txnMap.commit();
assertEquals(2, txnMap.size());
}
@Test
public void testMapIterateEntries3() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapIterateEntries3");
txnMap.put("1", "value1");
assertEquals(1, txnMap.size());
txnMap.begin();
txnMap.put("1", "value2");
assertEquals(1, txnMap.size());
Set<Map.Entry> entries = txnMap.entrySet();
for (Map.Entry entry : entries) {
if ("1".equals(entry.getKey())) {
assertEquals("value2", entry.getValue());
} else throw new RuntimeException("cannot contain another entry with key " + entry.getKey());
}
txnMap.rollback();
assertEquals(1, txnMap.size());
entries = txnMap.entrySet();
for (Map.Entry entry : entries) {
if ("1".equals(entry.getKey())) {
assertEquals("value1", entry.getValue());
} else throw new RuntimeException("cannot contain another entry with key " + entry.getKey());
}
}
@Test
public void testMapPutCommitSize() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapPutCommitSize");
IMap imap = newMapProxy("testMapPutCommitSize");
txnMap.put("1", "item");
assertEquals(1, txnMap.size());
assertEquals(1, imap.size());
txnMap.begin();
txnMap.put(2, "newone");
assertEquals(2, txnMap.size());
assertEquals(1, imap.size());
txnMap.commit();
assertEquals(2, txnMap.size());
assertEquals(2, imap.size());
}
@Test
public void testMapPutRollbackSize() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapPutRollbackSize");
IMap imap = newMapProxy("testMapPutRollbackSize");
txnMap.put("1", "item");
assertEquals(1, txnMap.size());
assertEquals(1, imap.size());
txnMap.begin();
txnMap.put(2, "newone");
assertEquals(2, txnMap.size());
assertEquals(1, imap.size());
txnMap.rollback();
assertEquals(1, txnMap.size());
assertEquals(1, imap.size());
assertNull(imap.getMapEntry(2));
assertNull(imap.get(2));
}
@Test
public void testSetCommit() {
TransactionalSet set = newTransactionalSetProxy("testSetCommit");
set.begin();
set.add("item");
assertEquals(1, set.size());
set.commit();
assertEquals(1, set.size());
}
@Test
public void testSetCommitTwoSameItems() {
TransactionalSet set = newTransactionalSetProxy("testSetCommitTwoSameItems");
set.begin();
set.add("item");
set.add("item");
assertEquals(1, set.size());
set.commit();
assertEquals(1, set.size());
}
@Test
public void testSetRollback() {
TransactionalSet set = newTransactionalSetProxy("testSetRollback");
set.begin();
set.add("item");
set.rollback();
assertEquals(0, set.size());
}
@Test
public void testListCommit() {
TransactionalList list = newTransactionalListProxy("testListCommit");
list.begin();
list.add("item");
assertEquals(1, list.size());
list.commit();
assertEquals(1, list.size());
}
@Test
public void testListCommitTwoSameItems() {
TransactionalList list = newTransactionalListProxy("testListCommitTwoSameItems");
list.begin();
list.add("item");
list.add("item");
assertEquals(2, list.size());
list.commit();
assertEquals(2, list.size());
}
@Test
public void testListRollback() {
TransactionalList list = newTransactionalListProxy("testListRollback");
list.begin();
list.add("item");
list.rollback();
assertEquals(0, list.size());
}
@Test
public void testSetAddWithTwoTxn() {
Hazelcast.getSet("testSetAddWithTwoTxn").add("1");
Hazelcast.getSet("testSetAddWithTwoTxn").add("1");
TransactionalSet set = newTransactionalSetProxy("testSetAddWithTwoTxn");
TransactionalSet set2 = newTransactionalSetProxy("testSetAddWithTwoTxn");
assertEquals(1, set.size());
assertEquals(1, set2.size());
set.begin();
set.add("2");
assertEquals(2, set.size());
assertEquals(1, set2.size());
set.commit();
assertEquals(2, set.size());
assertEquals(2, set2.size());
set2.begin();
assertEquals(2, set.size());
assertEquals(2, set2.size());
set2.remove("1");
assertEquals(2, set.size());
assertEquals(1, set2.size());
set2.commit();
assertEquals(1, set.size());
assertEquals(1, set2.size());
}
@Test
public void testMapPutWithTwoTxn() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapPutWithTwoTxn");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapPutWithTwoTxn");
txnMap.begin();
txnMap.put("1", "value");
assertEquals("value", txnMap.get("1"));
txnMap.put("1", "value1");
assertEquals("value1", txnMap.get("1"));
txnMap.commit();
assertEquals("value1", txnMap.get("1"));
txnMap2.begin();
assertEquals("value1", txnMap2.put("1", "value2"));
assertEquals("value2", txnMap2.get("1"));
txnMap2.commit();
assertEquals("value2", txnMap.get("1"));
assertEquals("value2", txnMap2.get("1"));
}
// @Test
// public void testMapGetOnlyWithTwoTxn() {
// TransactionalMap txnMap = newTransactionalMapProxy("testMapGetOnlyWithTwoTxn");
// TransactionalMap txnMap2 = newTransactionalMapProxy("testMapGetOnlyWithTwoTxn");
// txnMap.begin();
// assertNull(txnMap.get("1"));
// txnMap2.begin();
// txnMap2.put("1", "value1");
// assertEquals("value1", txnMap2.get("1"));
// assertNull(txnMap.get("1"));
// txnMap2.commit();
// assertNull(txnMap.get("1"));
// txnMap.commit();
// assertEquals("value1", txnMap.get("1"));
// assertEquals("value1", txnMap2.get("1"));
// }
/**
* issue 455
*/
@Test
public void testPutIfAbsentInTxn() {
IMap<String, String> aMap = Hazelcast.getMap("testPutIfAbsentInTransaction");
Transaction txn = Hazelcast.getTransaction();
txn.begin();
try {
aMap.put("key1", "value1");
assertEquals("value1", aMap.putIfAbsent("key1", "value3"));
aMap.put("key1", "value1");
txn.commit();
} catch (Throwable t) {
txn.rollback();
}
assertEquals("value1", aMap.get("key1"));
assertEquals("value1", aMap.putIfAbsent("key1", "value3"));
assertEquals("value1", aMap.get("key1"));
txn = Hazelcast.getTransaction();
txn.begin();
try {
assertEquals("value1", aMap.get("key1"));
assertEquals("value1", aMap.putIfAbsent("key1", "value2"));
assertEquals("value1", aMap.get("key1"));
txn.commit();
} catch (Throwable t) {
txn.rollback();
}
assertEquals("value1", aMap.get("key1"));
}
@Test
public void testMapRemoveWithTwoTxn() {
IMap map = Hazelcast.getMap("testMapRemoveWithTwoTxn");
map.put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testMapRemoveWithTwoTxn");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapRemoveWithTwoTxn");
txnMap.begin();
assertEquals("value", txnMap.remove("1"));
assertEquals(0, txnMap.size());
assertEquals(1, map.size());
assertFalse(txnMap.containsKey("1"));
assertTrue(map.containsKey("1"));
txnMap.commit();
assertEquals(0, txnMap.size());
assertEquals(0, map.size());
assertFalse(txnMap.containsKey("1"));
assertFalse(map.containsKey("1"));
txnMap2.begin();
txnMap2.remove("1");
txnMap2.commit();
}
@Test
public void testTryLock() {
Hazelcast.getMap("testTryLock").put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testTryLock");
TransactionalMap txnMap2 = newTransactionalMapProxy("testTryLock");
txnMap.lock("1");
long start = System.currentTimeMillis();
assertFalse(txnMap2.tryLock("1", 2, TimeUnit.SECONDS));
long end = System.currentTimeMillis();
long took = (end - start);
assertTrue((took > 1000) ? (took < 4000) : false);
assertFalse(txnMap2.tryLock("1"));
txnMap.unlock("1");
assertTrue(txnMap2.tryLock("1", 2, TimeUnit.SECONDS));
}
@Test
public void testReentrantLock() {
Hazelcast.getMap("testReentrantLock").put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testReentrantLock");
TransactionalMap txnMap2 = newTransactionalMapProxy("testReentrantLock");
try {
assertEquals("value", txnMap.tryLockAndGet("1", 5, TimeUnit.SECONDS));
} catch (TimeoutException e) {
fail();
}
txnMap.lock("1");
assertFalse(txnMap2.tryLock("1"));
txnMap.unlock("1");
assertFalse(txnMap2.tryLock("1"));
txnMap.unlock("1");
assertTrue(txnMap2.tryLock("1"));
}
@Test(timeout = 100000)
public void testTransactionCommitRespectLockCount() throws InterruptedException {
Hazelcast.getMap("testTransactionCommitRespectLockCount").put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testTransactionCommitRespectLockCount");
TransactionalMap txnMap2 = newTransactionalMapProxy("testTransactionCommitRespectLockCount");
txnMap.lock(1);
txnMap.begin();
txnMap.put(1, "value");
txnMap.commit();
assertFalse("Shouldn't acquire lock", txnMap2.tryLock(1));
txnMap.unlock(1);
Assert.assertTrue(txnMap2.tryLock(1));
}
@Test
public void testTryLock2() throws Exception {
Hazelcast.getMap("testTryLock").put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testTryLock");
final TransactionalMap txnMap2 = newTransactionalMapProxy("testTryLock");
txnMap.lock("1");
Future f = txnMap2.async("tryLock", "1", 101, TimeUnit.MILLISECONDS);
Thread.sleep(2100);
txnMap.unlock("1");
assertFalse((Boolean) f.get(3, TimeUnit.SECONDS));
}
@Test
public void testMapRemoveAndLock() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapRemoveAndLock");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapRemoveAndLock");
txnMap.put("Hello", "World");
txnMap.remove("Hello");
assertTrue(txnMap.tryLock("Hello"));
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
}
assertEquals(false, txnMap2.tryLock("Hello"));
}
@Test
public void testTryPut2() {
IMap map = Hazelcast.getMap("testTryPut");
map.tryPut("1", "value", 5, TimeUnit.SECONDS);
}
@Test
public void testTryPut() {
Map map = Hazelcast.getMap("testTryPut");
map.put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testTryPut");
TransactionalMap txnMap2 = newTransactionalMapProxy("testTryPut");
txnMap.lock("1");
long start = System.currentTimeMillis();
assertFalse(txnMap2.tryPut("1", "value2", 2, TimeUnit.SECONDS));
long end = System.currentTimeMillis();
long took = (end - start);
assertTrue((took > 1000) ? (took < 4000) : false);
assertEquals("value", map.get("1"));
assertEquals("value", txnMap.get("1"));
assertEquals("value", txnMap2.get("1"));
txnMap.unlock("1");
assertTrue(txnMap2.tryPut("1", "value2", 2, TimeUnit.SECONDS));
assertEquals("value2", map.get("1"));
assertEquals("value2", txnMap.get("1"));
assertEquals("value2", txnMap2.get("1"));
}
@Test
public void testMapRemoveRollback() {
Hazelcast.getMap("testMapRemoveRollback").put("1", "value");
TransactionalMap txnMap = newTransactionalMapProxy("testMapRemoveRollback");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapRemoveRollback");
txnMap.begin();
assertEquals(1, txnMap.size());
txnMap.remove("1");
assertEquals(0, txnMap.size());
assertEquals(1, txnMap2.size());
txnMap.rollback();
assertEquals(1, txnMap.size());
assertEquals(1, txnMap2.size());
txnMap2.begin();
txnMap2.remove("1");
txnMap2.commit();
assertEquals(0, txnMap.size());
assertEquals(0, txnMap2.size());
}
@Test
public void testMapRemoveWithTwoTxn2() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapRemoveWithTwoTxn2");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapRemoveWithTwoTxn2");
txnMap.begin();
txnMap.remove("1");
txnMap.commit();
txnMap2.begin();
txnMap2.remove("1");
txnMap2.commit();
}
@Test
public void testMapTryRemove() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapTryRemove");
IMap txnMap2 = Hazelcast.getMap("testMapTryRemove");
txnMap.put("1", "value1");
txnMap.lock("1");
assertEquals("value1", txnMap.get("1"));
assertEquals("value1", txnMap2.get("1"));
long start = System.currentTimeMillis();
try {
assertNull(txnMap2.tryRemove("1", 0, TimeUnit.SECONDS));
fail("Shouldn't be able to remove");
} catch (TimeoutException e) {
assertTrue(System.currentTimeMillis() - start < 1000);
}
start = System.currentTimeMillis();
try {
assertNull(txnMap2.tryRemove("1", 3, TimeUnit.SECONDS));
fail("Shouldn't be able to remove");
} catch (TimeoutException e) {
long took = (System.currentTimeMillis() - start);
assertTrue(took >= 3000 && took < 5000);
}
txnMap.unlock("1");
try {
assertEquals("value1", txnMap2.tryRemove("1", 0, TimeUnit.SECONDS));
} catch (TimeoutException e) {
fail();
}
assertNull(txnMap.get("1"));
assertNull(txnMap2.get("1"));
assertEquals(0, txnMap.size());
assertEquals(0, txnMap2.size());
}
@Test
public void testMapTryLockAndGet() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapTryLockAndGet");
IMap txnMap2 = Hazelcast.getMap("testMapTryLockAndGet");
txnMap.put("1", "value1");
try {
assertEquals("value1", txnMap.tryLockAndGet("1", 0, TimeUnit.SECONDS));
} catch (TimeoutException e) {
fail();
}
assertEquals("value1", txnMap.get("1"));
assertEquals("value1", txnMap2.get("1"));
long start = System.currentTimeMillis();
try {
txnMap2.tryLockAndGet("1", 0, TimeUnit.SECONDS);
fail("Shouldn't be able to lock");
} catch (TimeoutException e) {
assertTrue(System.currentTimeMillis() - start < 1000);
}
start = System.currentTimeMillis();
try {
assertNull(txnMap2.tryLockAndGet("1", 3, TimeUnit.SECONDS));
fail("Shouldn't be able to lock");
} catch (TimeoutException e) {
long took = (System.currentTimeMillis() - start);
assertTrue(took >= 3000 && took < 5000);
}
txnMap.putAndUnlock("1", "value2");
try {
assertEquals("value2", txnMap2.tryLockAndGet("1", 0, TimeUnit.SECONDS));
} catch (TimeoutException e) {
fail();
}
assertEquals("value2", txnMap.get("1"));
assertEquals("value2", txnMap2.get("1"));
}
@Test
public void testMapRemoveWithTwoTxn3() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapRemoveWithTwoTxn3");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapRemoveWithTwoTxn3");
txnMap.put("1", "value1");
assertEquals(1, txnMap.size());
assertEquals(1, txnMap2.size());
txnMap.begin();
txnMap.remove("1");
assertEquals(0, txnMap.size());
assertEquals(1, txnMap2.size());
txnMap.commit();
assertEquals(0, txnMap.size());
assertEquals(0, txnMap2.size());
txnMap.put("1", "value1");
assertEquals(1, txnMap.size());
assertEquals(1, txnMap2.size());
txnMap2.begin();
txnMap2.remove("1");
assertEquals(1, txnMap.size());
assertEquals(0, txnMap2.size());
txnMap2.commit();
assertEquals(0, txnMap.size());
assertEquals(0, txnMap2.size());
}
@Test
public void testMultiMapPutWithTwoTxn() {
TransactionalMultiMap txnMMap = newTransactionalMultiMapProxy("testMultiMapPutWithTwoTxn");
TransactionalMultiMap txnMMap2 = newTransactionalMultiMapProxy("testMultiMapPutWithTwoTxn");
txnMMap.begin();
assertTrue(txnMMap.put("1", "value1"));
assertEquals(1, txnMMap.size());
assertEquals(0, txnMMap2.size());
txnMMap.commit();
assertEquals(1, txnMMap.size());
assertEquals(1, txnMMap2.size());
txnMMap2.begin();
assertTrue(txnMMap2.put("1", "value2"));
assertEquals(1, txnMMap.size());
assertEquals(2, txnMMap2.size());
txnMMap2.commit();
assertEquals(2, txnMMap.size());
assertEquals(2, txnMMap2.size());
assertEquals(2, txnMMap.valueCount("1"));
assertEquals(2, txnMMap2.valueCount("1"));
}
@Test
public void testMultiMapRemoveWithTwoTxn() {
MultiMap mmap = Hazelcast.getMultiMap("testMultiMapRemoveWithTwoTxn");
assertTrue(mmap.put("1", "value1"));
assertTrue(mmap.put("1", "value2"));
assertTrue(mmap.put("1", "value3"));
TransactionalMultiMap txnMMap = newTransactionalMultiMapProxy("testMultiMapRemoveWithTwoTxn");
TransactionalMultiMap txnMMap2 = newTransactionalMultiMapProxy("testMultiMapRemoveWithTwoTxn");
assertEquals(3, mmap.size());
txnMMap.begin();
assertTrue(txnMMap.remove("1", "value2"));
assertFalse(txnMMap.remove("1", "value5"));
assertEquals(2, txnMMap.size());
assertEquals(3, txnMMap2.size());
txnMMap.commit();
assertEquals(2, mmap.size());
txnMMap2.begin();
assertEquals(2, mmap.size());
assertEquals(2, txnMMap2.size());
Collection values = txnMMap2.remove("1");
assertEquals(2, values.size());
assertEquals(2, txnMMap.size());
assertEquals(0, txnMMap2.size());
txnMMap2.commit();
assertEquals(0, mmap.size());
}
@Test
public void testMultiMapPutRemoveWithTxn() {
MultiMap multiMap = Hazelcast.getMultiMap("testMultiMapPutRemoveWithTxn");
multiMap.put("1", "C");
multiMap.put("2", "x");
multiMap.put("2", "y");
TransactionalMultiMap txnMap = newTransactionalMultiMapProxy("testMultiMapPutRemoveWithTxn");
txnMap.begin();
txnMap.put("1", "A");
txnMap.put("1", "B");
Collection g1 = txnMap.get("1");
System.err.println(g1);
assertTrue(g1.contains("A"));
assertTrue(g1.contains("B"));
assertTrue(g1.contains("C"));
assertTrue(txnMap.remove("1", "C"));
assertEquals(4, txnMap.size());
Collection g2 = txnMap.get("1");
assertTrue(g2.contains("A"));
assertTrue(g2.contains("B"));
assertFalse(g2.contains("C"));
Collection r1 = txnMap.remove("2");
assertTrue(r1.contains("x"));
assertTrue(r1.contains("y"));
assertNull(txnMap.get("2"));
Collection r2 = txnMap.remove("1");
assertEquals(2, r2.size());
assertTrue(r2.contains("A"));
assertTrue(r2.contains("B"));
assertNull(txnMap.get("1"));
txnMap.commit();
assertEquals(0, txnMap.size());
}
@Test
public void testQueueOfferCommitSize() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueueOfferCommitSize");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueueOfferCommitSize");
txnq.begin();
txnq.offer("item");
assertEquals(1, txnq.size());
assertEquals(0, txnq2.size());
txnq.commit();
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
assertEquals("item", txnq2.poll());
}
@Test
public void testQueueOfferRollbackSize() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueueOfferRollbackSize");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueueOfferRollbackSize");
txnq.begin();
txnq.offer("item");
assertEquals(1, txnq.size());
assertEquals(0, txnq2.size());
txnq.rollback();
assertEquals(0, txnq.size());
assertEquals(0, txnq2.size());
}
@Test
public void testQueueOfferCommitIterator() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueueOfferCommitIterator");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueueOfferCommitIterator");
assertEquals(0, txnq.size());
assertEquals(0, txnq2.size());
txnq.begin();
txnq.offer("item");
Iterator it = txnq.iterator();
int size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
it = txnq2.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(0, size);
txnq.commit();
it = txnq.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
it = txnq2.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
}
@Test
public void testQueueOfferCommitIterator2() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueueOfferCommitIterator2");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueueOfferCommitIterator2");
txnq.offer("item0");
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
txnq.begin();
txnq.offer("item");
Iterator it = txnq.iterator();
int size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(2, size);
it = txnq2.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
txnq.commit();
it = txnq.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(2, size);
it = txnq2.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(2, size);
assertEquals(2, txnq.size());
assertEquals(2, txnq2.size());
}
@Test
public void testQueueOfferRollbackIterator2() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueueOfferRollbackIterator2");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueueOfferRollbackIterator2");
txnq.offer("item0");
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
txnq.begin();
txnq.offer("item");
Iterator it = txnq.iterator();
int size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(2, size);
it = txnq2.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
txnq.rollback();
it = txnq.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
it = txnq2.iterator();
size = 0;
while (it.hasNext()) {
assertNotNull(it.next());
size++;
}
assertEquals(1, size);
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
}
@Test
public void testQueuePollCommitSize() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueuePollCommitSize");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueuePollCommitSize");
txnq.offer("item1");
txnq.offer("item2");
assertEquals(2, txnq.size());
assertEquals(2, txnq2.size());
txnq.begin();
assertEquals("item1", txnq.poll());
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
txnq.commit();
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
assertEquals("item2", txnq2.poll());
assertEquals(0, txnq.size());
assertEquals(0, txnq2.size());
}
@Test
public void testQueuePollRollbackSize() {
TransactionalQueue txnq = newTransactionalQueueProxy("testQueuePollRollbackSize");
TransactionalQueue txnq2 = newTransactionalQueueProxy("testQueuePollRollbackSize");
txnq.offer("item1");
txnq.offer("item2");
assertEquals(2, txnq.size());
assertEquals(2, txnq2.size());
txnq.begin();
assertEquals("item1", txnq.poll());
assertEquals(1, txnq.size());
assertEquals(1, txnq2.size());
txnq.rollback();
assertEquals(2, txnq.size());
assertEquals(2, txnq2.size());
assertEquals("item1", txnq2.poll());
assertEquals("item2", txnq2.poll());
}
@Test
public void testQueueOrderAfterPollRollback() {
IQueue<Integer> queue = newQueueProxy("testQueueOrderAfterPollRollback");
TransactionalQueue<Integer> txn1 = newTransactionalQueueProxy("testQueueOrderAfterPollRollback");
txn1.begin();
txn1.offer(1);
txn1.offer(2);
txn1.offer(3);
txn1.commit();
assertEquals(3, queue.size());
assertEquals(3, txn1.size());
TransactionalQueue<Integer> txn2 = newTransactionalQueueProxy("testQueueOrderAfterPollRollback");
txn2.begin();
assertEquals(1, txn2.poll().intValue());
assertEquals(2, txn2.peek().intValue());
txn2.rollback();
assertEquals(1, queue.poll().intValue());
assertEquals(2, queue.poll().intValue());
assertEquals(3, queue.poll().intValue());
}
@Test
@Ignore
public void testMapEntryLastAccessTime() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapEntryLastAccessTime");
TransactionalMap txnMap2 = newTransactionalMapProxy("testMapEntryLastAccessTime");
txnMap.put("1", "value1");
MapEntry mapEntry = txnMap.getMapEntry("1");
txnMap.begin();
txnMap.get("1");
mapEntry = txnMap.getMapEntry("1");
System.out.println("txn test time2 " + mapEntry.getLastAccessTime());
txnMap.commit();
}
@After
public void cleanUp() {
Iterator<Instance> it = mapsUsed.iterator();
while (it.hasNext()) {
Instance instance = it.next();
instance.destroy();
}
mapsUsed.clear();
}
static class Thing implements Serializable {
String property;
Thing(String property) {
this.property = property;
}
String getProperty() {
return property;
}
}
@Test
public void testMapPutPredicate() {
TransactionalMap txnMap = newTransactionalMapProxy("testMapPutPredicate");
txnMap.begin();
txnMap.put("1", new Thing("thing1"));
txnMap.put("2", new Thing("thing2"));
txnMap.put("3", new Thing("thing3"));
EntryObject e = new PredicateBuilder().getEntryObject();
Predicate predicate = e.get("property").equal("thing2");
assertEquals(1, txnMap.values(predicate).size());
txnMap.commit();
assertEquals(3, txnMap.size());
}
@Test
public void issue581testRemoveInTwoTransactionOneShouldReturnNull() throws InterruptedException {
final IMap m = Hazelcast.getMap("test");
final AtomicReference<Object> t1Return = new AtomicReference<Object>();
final AtomicReference<Object> t2Return = new AtomicReference<Object>();
// final CountDownLatch latch = new CountDownLatch(1);
m.put("a", "b");
//Start the first thread, acquire the lock and call remove
new Thread("1. thread") {
@Override
public void run() {
try {
Transaction tx = Hazelcast.getTransaction();
tx.begin();
t1Return.set(m.remove("a"));
Thread.sleep(1000);
tx.commit();
} catch (InterruptedException ex) {
}
}
}.start();
//Start the second thread, ensure it call remove after tx in thread1 is committed
Thread t2 = new Thread("2. thread") {
@Override
public void run() {
try {
Transaction tx = Hazelcast.getTransaction();
tx.begin();
Thread.sleep(1000);//Make sure the first thread acquires the lock
t2Return.set(m.remove("a"));
tx.commit();
} catch (InterruptedException ex) {
}
}
};
t2.start();
t2.join();
Assert.assertEquals("b", t1Return.get());
Assert.assertNull("The remove in the second thread should return null", t2Return.get());
Hazelcast.shutdownAll();
}
@Test
public void issue770TestIMapTryPutUnderTransaction() {
final HazelcastInstance hz = Hazelcast.getDefaultInstance();
Transaction tx = hz.getTransaction();
tx.begin();
IMap<Object, Object> map = hz.getMap("test");
Assert.assertTrue(map.tryPut("key", "value", 100, TimeUnit.MILLISECONDS));
Assert.assertTrue(map.tryPut("key", "value2", 100, TimeUnit.MILLISECONDS));
tx.commit();
Hazelcast.shutdownAll();
}
final List<Instance> mapsUsed = new CopyOnWriteArrayList<Instance>();
TransactionalMap newTransactionalMapProxy(String name) {
return (TransactionalMap) newTransactionalProxy(Hazelcast.getMap(name), TransactionalMap.class);
}
TransactionalMultiMap newTransactionalMultiMapProxy(String name) {
return (TransactionalMultiMap) newTransactionalProxy(Hazelcast.getMultiMap(name), TransactionalMultiMap.class);
}
TransactionalQueue newTransactionalQueueProxy(String name) {
return (TransactionalQueue) newTransactionalProxy(Hazelcast.getQueue(name), TransactionalQueue.class);
}
TransactionalSet newTransactionalSetProxy(String name) {
return (TransactionalSet) newTransactionalProxy(Hazelcast.getSet(name), TransactionalSet.class);
}
TransactionalList newTransactionalListProxy(String name) {
return (TransactionalList) newTransactionalProxy(Hazelcast.getList(name), TransactionalList.class);
}
<T extends Instance> T newTransactionalProxy(Instance instance, Class klass) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class[] interfaces = new Class[]{klass};
Object proxy = Proxy.newProxyInstance(classLoader, interfaces, new ThreadBoundInvocationHandler(instance));
T txnInstance = (T) proxy;
mapsUsed.add(txnInstance);
return txnInstance;
}
IMap newMapProxy(String name) {
return newMapProxy(Hazelcast.getDefaultInstance(), name, mapsUsed);
}
public static IMap newMapProxy(HazelcastInstance hz, String name, List listToAdd) {
IMap imap = hz.getMap(name);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class[] interfaces = new Class[]{IMap.class};
IMap proxy = (IMap) Proxy.newProxyInstance(classLoader, interfaces, new ThreadBoundInvocationHandler(imap));
if (listToAdd != null) {
listToAdd.add(proxy);
}
return proxy;
}
IQueue newQueueProxy(String name) {
return newQueueProxy(Hazelcast.getDefaultInstance(), name, mapsUsed);
}
public static IQueue newQueueProxy(HazelcastInstance hz, String name, List listToAdd) {
IQueue queue = hz.getQueue(name);
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Class[] interfaces = new Class[]{IQueue.class};
IQueue proxy = (IQueue) Proxy.newProxyInstance(classLoader, interfaces, new ThreadBoundInvocationHandler(queue));
if (listToAdd != null) {
listToAdd.add(proxy);
}
return proxy;
}
interface TransactionalMultiMap extends MultiMap {
void begin();
void commit();
void rollback();
}
interface TransactionalMap extends IMap {
Future async(String methodName, Object... arg);
void begin();
void commit();
void rollback();
}
interface TransactionalQueue<E> extends IQueue<E> {
void begin();
void commit();
void rollback();
}
interface TransactionalSet extends ISet {
void begin();
void commit();
void rollback();
}
interface TransactionalList extends IList {
void begin();
void commit();
void rollback();
}
public static class ThreadBoundInvocationHandler implements InvocationHandler {
final Object target;
final ExecutorService es = Executors.newSingleThreadExecutor();
final static Object NULL_OBJECT = new Object();
public ThreadBoundInvocationHandler(Object target) {
this.target = target;
}
public Object invoke(final Object o, final Method method, final Object[] args) throws Throwable {
final String name = method.getName();
final BlockingQueue<Object> resultQ = ResponseQueueFactory.newResponseQueue();
if (name.equals("async")) {
return invokeAsync(args);
} else if (name.equals("begin") || name.equals("commit") || name.equals("rollback")) {
es.execute(new Runnable() {
public void run() {
try {
Transaction txn = Hazelcast.getTransaction();
if (name.equals("begin")) {
txn.begin();
} else if (name.equals("commit")) {
txn.commit();
} else if (name.equals("rollback")) {
txn.rollback();
}
resultQ.put(NULL_OBJECT);
} catch (Exception e) {
try {
resultQ.put(e);
} catch (InterruptedException ignored) {
}
}
}
});
} else {
es.execute(new Runnable() {
public void run() {
try {
Object result = method.invoke(target, args);
resultQ.put((result == null) ? NULL_OBJECT : result);
} catch (Exception e) {
try {
resultQ.put(e);
} catch (InterruptedException ignored) {
}
}
}
});
}
Object result = resultQ.poll(5, TimeUnit.SECONDS);
if (result == null) throw new RuntimeException("Method [" + name + "] took more than 5 seconds!");
if (name.equals("destroy")) {
es.shutdown();
}
if (result instanceof Throwable) {
throw ((Throwable) result);
}
return (result == NULL_OBJECT) ? null : result;
}
public Future invokeAsync(final Object[] args) throws Exception {
String methodName = (String) args[0];
final Object[] newArgs = (args.length == 1) ? null : (Object[]) args[1];
int len = (newArgs == null) ? 0 : newArgs.length;
final Method method = findMethod(methodName, len);
return es.submit(new Callable() {
public Object call() throws Exception {
return method.invoke(target, newArgs);
}
});
}
private Method findMethod(String name, int argLen) {
Method[] methods = target.getClass().getMethods();
for (Method method : methods) {
if (method.getName().equals(name)) {
if (argLen == method.getParameterTypes().length) {
return method;
}
}
}
return null;
}
}
}