/*
* JBoss, Home of Professional Open Source
* Copyright 2009 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt in the distribution for a full listing of
* individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.infinispan.distribution;
import org.infinispan.Cache;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.test.TestingUtil;
import org.infinispan.util.concurrent.locks.LockManager;
import org.testng.annotations.Test;
import javax.transaction.TransactionManager;
@Test(groups = "functional", enabled=false, testName = "distribution.DistSyncTxFuncTest")
public class DistSyncTxFuncTest extends BaseDistFunctionalTest {
public DistSyncTxFuncTest() {
sync = true;
tx = true;
testRetVals = true;
cleanup = CleanupPhase.AFTER_METHOD; // ensure any stale TXs are wiped
}
protected void asyncTxWait(Object... keys) {
// no op. Meant to be overridden
}
protected void init(MagicKey k1, MagicKey k2) {
// neither key maps on to c4
c2.put(k1, "value1");
asyncWait(k1, PutKeyValueCommand.class, c1, c3, c4);
c2.put(k2, "value2");
asyncWait(k2, PutKeyValueCommand.class, c1, c3, c4);
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
}
public void testTransactionsSpanningKeysCommit() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
// now test a transaction that spans both keys.
TransactionManager tm4 = getTransactionManager(c4);
asserLocked(c3, false, k1);
tm4.begin();
c4.put(k1, "new_value1");
c4.put(k2, "new_value2");
tm4.commit();
asyncTxWait("new_value1", "new_value2");
asserLocked(c3, false, k1);
asserLocked(c3, false, k2);
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsInL1(c4, k1);
assertIsInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
asserLocked(c4, false, k1, k2);
asserLocked(c3, false, k1);
asserLocked(c3, false, k2);
asserLocked(c1, false, k1, k2);
asserLocked(c2, false, k1, k2);
checkOwnership(k1, k2, "new_value1", "new_value2");
}
void asserLocked(Cache c, boolean isLocked, Object... keys) {
LockManager lm = TestingUtil.extractComponent(c, LockManager.class);
for (Object key : keys) {
assert isLocked == lm.isLocked(key) : " expecting key '" + key + "' to be " + (isLocked ? " locked " :
"not locked + \n Lock owner is:" + lm.getOwner(key));
}
}
protected void checkOwnership(MagicKey k1, MagicKey k2, String v1, String v2) {
assertOnAllCachesAndOwnership(k1, v1);
assertOnAllCachesAndOwnership(k2, v2);
assertIsInL1(c4, k1);
assertIsInL1(c4, k2);
assertIsInL1(c1, k2);
assertIsInL1(c3, k1);
}
public void testTransactionsSpanningKeysRollback() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
// now test a transaction that spans both keys.
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
c4.put(k1, "new_value1");
c4.put(k2, "new_value2");
tm4.rollback();
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
checkOwnership(k1, k2, "value1", "value2");
}
public void testPutFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
Object ret = c4.put(k1, "new_value");
if (testRetVals) assert "value1".equals(ret);
ret = c4.put(k2, "new_value");
if (testRetVals) assert "value2".equals(ret);
tm4.rollback();
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
checkOwnership(k1, k2, "value1", "value2");
}
public void testPutIfAbsentFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
TransactionManager tm4 = getTransactionManager(c4);
LockManager lockManager4 = TestingUtil.extractComponent(c4, LockManager.class);
tm4.begin();
Object ret = c4.putIfAbsent(k1, "new_value");
if (testRetVals) assert "value1".equals(ret) : "Was expecting value1 but was " + ret;
ret = c4.putIfAbsent(k2, "new_value");
if (testRetVals) assert "value2".equals(ret) : "Was expecting value2 but was " + ret;
assert c4.get(k1).equals("value1");
assert c4.get(k2).equals("value2");
assert lockManager4.isLocked(k1);
assert lockManager4.isLocked(k2);
tm4.rollback();
assert !lockManager4.isLocked(k1);
assert !lockManager4.isLocked(k2);
assert c2.get(k1).equals("value1");
assert c2.get(k2).equals("value2");
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
checkOwnership(k1, k2, "value1", "value2");
}
public void testRemoveFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
asserLocked(c1, false, k1, k2);
asserLocked(c2, false, k1, k2);
asserLocked(c3, false, k1, k2);
asserLocked(c4, false, k1, k2);
log.info("***** Here it starts!");
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
Object ret = c4.remove(k1);
if (testRetVals) assert "value1".equals(ret);
ret = c4.remove(k2);
if (testRetVals) assert "value2".equals(ret);
assert !c4.containsKey(k1);
assert !c4.containsKey(k2);
tm4.rollback();
log.info("----- Here it ends!");
asserLocked(c1, false, k1, k2);
asserLocked(c2, false, k1, k2);
asserLocked(c3, false, k1, k2);
asserLocked(c4, false, k1 );
asserLocked(c4, false, k2 );
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
asserLocked(c1, false, k1, k2);
asserLocked(c2, false, k1, k2);
asserLocked(c3, false, k1, k2);
asserLocked(c4, false, k1, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
asserLocked(c1, false, k1, k2);
asserLocked(c2, false, k1, k2);
asserLocked(c3, false, k1, k2);
asserLocked(c4, false, k1, k2);
checkOwnership(k1, k2, "value1", "value2");
}
public void testConditionalRemoveFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
boolean ret = c4.remove(k1, "valueX");
if (testRetVals) assert !ret;
ret = c4.remove(k2, "valueX");
if (testRetVals) assert !ret;
assert c4.containsKey(k1);
assert c4.containsKey(k2);
ret = c4.remove(k1, "value1");
if (testRetVals) assert ret;
ret = c4.remove(k2, "value2");
if (testRetVals) assert ret;
assert !c4.containsKey(k1);
assert !c4.containsKey(k2);
tm4.rollback();
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
checkOwnership(k1, k2, "value1", "value2");
}
public void testReplaceFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
Object ret = c4.replace(k1, "new_value");
if (testRetVals) assert "value1".equals(ret);
ret = c4.replace(k2, "new_value");
if (testRetVals) assert "value2".equals(ret);
assert "new_value".equals(c4.get(k1));
assert "new_value".equals(c4.get(k2));
tm4.rollback();
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
checkOwnership(k1, k2, "value1", "value2");
}
public void testConditionalReplaceFromNonOwner() throws Exception {
// we need 2 keys that reside on different caches...
MagicKey k1 = new MagicKey(c1, "k1"); // maps on to c1 and c2
MagicKey k2 = new MagicKey(c2, "k2"); // maps on to c2 and c3
init(k1, k2);
TransactionManager tm4 = getTransactionManager(c4);
tm4.begin();
boolean ret = c4.replace(k1, "valueX", "new_value");
if (testRetVals) assert !ret;
ret = c4.replace(k2, "valueX", "new_value");
if (testRetVals) assert !ret;
assert "value1".equals(c4.get(k1));
assert "value2".equals(c4.get(k2));
ret = c4.replace(k1, "value1", "new_value");
if (testRetVals) assert ret;
ret = c4.replace(k2, "value2", "new_value");
if (testRetVals) assert ret;
assert "new_value".equals(c4.get(k1));
assert "new_value".equals(c4.get(k2));
tm4.rollback();
assertIsInContainerImmortal(c1, k1);
assertIsInContainerImmortal(c2, k1);
assertIsInContainerImmortal(c2, k2);
assertIsInContainerImmortal(c3, k2);
assertIsNotInL1(c4, k1);
assertIsNotInL1(c4, k2);
assertIsNotInL1(c1, k2);
assertIsNotInL1(c3, k1);
checkOwnership(k1, k2, "value1", "value2");
}
}