private void testLockMigration(int nodeThatPuts) throws Exception { Map<Object, DummyTransaction> key2Tx = new HashMap<Object, DummyTransaction>(); for (int i = 0; i < NUM_KEYS; i++) { Object key = getKeyForCache(0); if (key2Tx.containsKey(key)) continue; dummyTm(nodeThatPuts).begin(); cache(nodeThatPuts).put(key, key); DummyTransaction tx = dummyTm(nodeThatPuts).getTransaction(); tx.runPrepare(); dummyTm(nodeThatPuts).suspend(); key2Tx.put(key, tx); assertLocked(0, key); } log.trace("Lock transfer happens here"); addClusterEnabledCacheManager(dccc); waitForClusterToForm(); Object migratedKey = null; ConsistentHash ch = advancedCache(2).getDistributionManager().getConsistentHash(); for (Object key : key2Tx.keySet()) { if (ch.locatePrimaryOwner(key).equals(address(2))) { migratedKey = key; break; } } if (migratedKey == null) { log.trace("No key migrated to new owner."); } else { log.trace("migratedKey = " + migratedKey); dummyTm(2).begin(); cache(2).put(migratedKey, "someValue"); try { dummyTm(2).commit(); fail("RollbackException should have been thrown here."); } catch (RollbackException e) { // expected } } log.trace("About to commit existing transactions."); log.trace("Committing the tx to the new node."); for (Transaction tx : key2Tx.values()) { tm(nodeThatPuts).resume(tx); dummyTm(nodeThatPuts).getTransaction().runCommitTx(); } for (Object key : key2Tx.keySet()) { Object value = getValue( key); // make sure that data from the container, just to make sure all replicas are // correctly set assertEquals(key, value); } }
public void testXidReturnedOnlyOnce() throws Throwable { DummyTransaction dummyTransaction1 = beginAndSuspendTx(this.cache(3)); prepareTransaction(dummyTransaction1); manager(3).stop(); TestingUtil.blockUntilViewsReceived(60000, false, cache(0), cache(1), cache(2)); DummyTransaction dummyTransaction = beginAndSuspendTx(this.cache(0)); Xid[] recover = dummyTransaction .firstEnlistedResource() .recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN); assertEquals(recover.length, 1); assertEquals(dummyTransaction1.getXid(), recover[0]); }
protected void doTest(final SplitMode splitMode, boolean txFail, boolean discard) throws Exception { waitForClusterToForm(OPTIMISTIC_TX_CACHE_NAME); final KeyInfo keyInfo = createKeys(OPTIMISTIC_TX_CACHE_NAME); final Cache<Object, String> originator = cache(0, OPTIMISTIC_TX_CACHE_NAME); final FilterCollection filterCollection = createFilters(OPTIMISTIC_TX_CACHE_NAME, discard, getCommandClass(), splitMode); Future<Void> put = fork( () -> { final DummyTransactionManager transactionManager = (DummyTransactionManager) originator.getAdvancedCache().getTransactionManager(); transactionManager.begin(); keyInfo.putFinalValue(originator); final DummyTransaction transaction = transactionManager.getTransaction(); transaction.runPrepare(); transaction.runCommit(forceRollback()); transaction.throwRollbackExceptionIfAny(); return null; }); filterCollection.await(30, TimeUnit.SECONDS); splitMode.split(this); filterCollection.unblock(); try { put.get(); assertFalse(txFail); } catch (ExecutionException e) { assertTrue(txFail); } checkLocksDuringPartition(splitMode, keyInfo, discard); mergeCluster(OPTIMISTIC_TX_CACHE_NAME); finalAsserts(OPTIMISTIC_TX_CACHE_NAME, keyInfo, txFail ? INITIAL_VALUE : FINAL_VALUE); }
protected void forgetWithInternalId(int cacheIndex) { long internalId = -1; for (RemoteTransaction rt : tt(1).getRemoteTransactions()) { RecoverableTransactionIdentifier a = (RecoverableTransactionIdentifier) rt.getGlobalTransaction(); if (a.getXid().equals(tx.getXid())) { internalId = a.getInternalId(); } } if (internalId == -1) throw new IllegalStateException(); log.tracef("About to forget... %s", internalId); recoveryOps(cacheIndex).forget(internalId); assertEquals(tt(0).getRemoteTxCount(), 0); assertEquals(tt(1).getRemoteTxCount(), 0); }
public void testPrimaryOwnerCrash() throws Exception { // cache 0 is the originator and backup, cache 1 is the primary owner StateSequencer ss = new StateSequencer(); ss.logicalThread("main", "block_prepare", "crash_primary", "resume_prepare"); tm(0).begin(); cache(0).put("k", "v1"); DummyTransaction tx1 = (DummyTransaction) tm(0).suspend(); tx1.runPrepare(); advanceOnInboundRpc(ss, cache(1), matchCommand(PrepareCommand.class).build()) .before("block_prepare", "resume_prepare"); Future<DummyTransaction> tx2Future = fork( () -> { tm(0).begin(); cache(0).put("k", "v2"); DummyTransaction tx2 = (DummyTransaction) tm(0).suspend(); tx2.runPrepare(); return tx2; }); ss.enter("crash_primary"); killMember(1); ss.exit("crash_primary"); DummyTransaction tx2 = tx2Future.get(10, SECONDS); try { tx2.runCommit(false); fail("tx2 should not be able to commit"); } catch (Exception e) { log.tracef(e, "Received expected exception"); } tx1.runCommit(false); }
private void forgetWithXid(int nodeIndex) { Xid xid = tx.getXid(); recoveryOps(nodeIndex) .forget(xid.getFormatId(), xid.getGlobalTransactionId(), xid.getBranchQualifier()); assertEquals(tt(1).getRemoteTxCount(), 0); // make sure tx has been removed }
public void testInternalIdOnSameNode() throws Exception { Xid xid = tx.getXid(); recoveryOps(0) .forget(xid.getFormatId(), xid.getGlobalTransactionId(), xid.getBranchQualifier()); assertEquals(tt(1).getRemoteTxCount(), 0); // make sure tx has been removed }