use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class TxRollbackAsyncTest method testRollbackProxy.
/**
* Tests proxy object returned by {@link IgniteTransactions#localActiveTransactions()}
*/
@Test
public void testRollbackProxy() throws Exception {
final GridFutureAdapter<Void> keyLocked = new GridFutureAdapter<>();
CountDownLatch waitCommit = new CountDownLatch(1);
Ignite ig = ignite(0);
IgniteInternalFuture<?> lockFut = lockInTx(ig, keyLocked, waitCommit, 0);
keyLocked.get();
Collection<Transaction> txs = ig.transactions().localActiveTransactions();
for (Transaction tx : txs) {
try {
tx.timeout(1);
fail("timeout");
} catch (Exception e) {
// No-op.
}
try {
tx.setRollbackOnly();
fail("setRollbackOnly");
} catch (Exception e) {
// No-op.
}
try {
tx.commit();
fail("commit");
} catch (Exception e) {
// No-op.
}
try {
tx.commitAsync();
fail("commitAsync");
} catch (Exception e) {
// No-op.
}
try {
tx.suspend();
fail("suspend");
} catch (Exception e) {
// No-op.
}
try {
tx.resume();
fail("resume");
} catch (Exception e) {
// No-op.
}
tx.rollback();
tx.rollbackAsync().get();
}
waitCommit.countDown();
try {
lockFut.get();
fail();
} catch (IgniteCheckedException e) {
// No-op.
}
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class TxPartitionCounterStateOnePrimaryTwoBackupsTest method testCommitReorderWithRollbackNoRebalanceAfterRestart.
/**
* Test scenario:
* <p>
* 1. Assign counters in order tx0, tx1
* <p>
* 2. Commit tx1.
* <p>
* 3. Prepare tx0 on both backups.
* <p>
* 4. Stop primary to trigger rollback on recovery.
* <p>
* 5. Stop backup1 without triggering checkpoint.
* <p>
* 6. Start backup1.
*
* Pass condition: backup1 has RollbackRecord in WAL closing the gap on logical recovery.
* After logical recovery no rebalancing must happen.
*
* @throws Exception If failed.
*/
@Test
public void testCommitReorderWithRollbackNoRebalanceAfterRestart() throws Exception {
int[] sizes = new int[] { 3, 7 };
int[] assignOrder = new int[] { 0, 1 };
int[] prepOrder = new int[] { 1, 0 };
Map<Integer, T2<Ignite, List<Ignite>>> txTops = runOnPartition(PARTITION_ID, null, BACKUPS, SERVERS_CNT, map -> {
Ignite primary = map.get(PARTITION_ID).get1();
return new TwoPhaseCommitTxCallbackAdapter(U.map((IgniteEx) primary, assignOrder), U.map((IgniteEx) primary, prepOrder), new HashMap<>(), sizes.length) {
@Override
protected boolean onPrimaryPrepared(IgniteEx primary, IgniteInternalTx tx, int idx) {
super.onPrimaryPrepared(primary, tx, idx);
// Prevent preparing tx0 on primary.
return idx == prepOrder[0];
}
@Override
public boolean afterPrimaryFinish(IgniteEx primary, IgniteUuid nearXidVer, GridFutureAdapter<?> proceedFut) {
log.info("TX: Finish primary " + order(nearXidVer));
runAsync(() -> stopGrid(true, primary.name()));
return super.afterPrimaryFinish(primary, nearXidVer, proceedFut);
}
};
}, sizes);
// SERVERS_CNT - 1 + client node.
waitForTopology(SERVERS_CNT);
awaitPartitionMapExchange();
// No gaps are expected on backups.
Ignite backup1 = txTops.get(PARTITION_ID).get2().get(0);
Ignite backup2 = txTops.get(PARTITION_ID).get2().get(1);
IgniteEx client = grid(CLIENT_GRID_NAME);
assertPartitionsSame(idleVerify(client, DEFAULT_CACHE_NAME));
assertCountersSame(PARTITION_ID, true, DEFAULT_CACHE_NAME);
PartitionUpdateCounter cntr1 = counter(PARTITION_ID, backup1.name());
assertNotNull(cntr1);
assertTrue(cntr1.sequential());
PartitionUpdateCounter cntr2 = counter(PARTITION_ID, backup2.name());
assertNotNull(cntr2);
assertTrue(cntr2.sequential());
stopGrid(true, backup1.name());
// Prevent rebalance from backup2.
TestRecordingCommunicationSpi spi = TestRecordingCommunicationSpi.spi(backup2);
spi.record(GridDhtPartitionSupplyMessage.class);
startGrid(backup1.name());
awaitPartitionMapExchange();
assertTrue(spi.recordedMessages(true).isEmpty());
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class TxPartitionCounterStateOnePrimaryTwoBackupsTest method doTestPartialPrepare_3tx.
/**
* Tests counters consistency when transaction is not prepared on second backup.
* <p>
* Scenario:
* <p>
* 1. Start 3 transactions.
* <p>
* 2. Assign counters in given order.
* <p>
* 3. Commit tx2.
* <p>
* 4. Prepare tx0 on backup1 (modes 0, 2).
* <p>
* 5. Prepare tx1 on backup2 (modes 1, 2).
* <p>
* 6. Fail primary triggering tx rollback on recovery.
* <p>
* 7. Validate partitions integrity after node left.
* <p>
* Pass condition: partitions are consistent, no holes are expected (they should be closed by message with counters)
*
* @param skipCheckpointOnNodeStop Skip checkpoint on node stop.
* @param assignOrder Tx assign order.
* @param mode Mode.
* @throws Exception If failed.
*/
private void doTestPartialPrepare_3tx(boolean skipCheckpointOnNodeStop, int[] assignOrder, int mode) throws Exception {
AtomicInteger cntr = new AtomicInteger();
int expCntr = mode == 2 ? 1 : 2;
Map<Integer, T2<Ignite, List<Ignite>>> txTops = runOnPartition(PARTITION_ID, null, BACKUPS, SERVERS_CNT, map -> {
Ignite primary = map.get(PARTITION_ID).get1();
Ignite backup1 = map.get(PARTITION_ID).get2().get(0);
Ignite backup2 = map.get(PARTITION_ID).get2().get(1);
return new TwoPhaseCommitTxCallbackAdapter(U.map((IgniteEx) primary, assignOrder), U.map((IgniteEx) backup1, new int[] { 2, 0, 1 }, (IgniteEx) backup2, new int[] { 2, 1, 0 }), new HashMap<>(), SIZES.length) {
@Override
protected boolean onBackupPrepared(IgniteEx backup, IgniteInternalTx tx, int idx) {
super.onBackupPrepared(backup, tx, idx);
switch(mode) {
case 0:
return idx == 0 && backup == backup1;
case 1:
return idx == 1 && backup == backup2;
case 2:
return idx == 0 && backup == backup1 || idx == 1 && backup == backup2;
}
return false;
}
@Override
public boolean afterPrimaryPrepare(IgniteEx primary, IgniteInternalTx tx, IgniteUuid nearXidVer, GridFutureAdapter<?> proceedFut) {
int idx = order(nearXidVer);
log.info("TX: primary prepared: [node=" + primary.name() + ", txId=" + idx + ']');
if (cntr.getAndIncrement() == expCntr) {
log.info("Stopping primary [name=" + primary.name() + ']');
runAsync(() -> stopGrid(skipCheckpointOnNodeStop, primary.name()));
}
return idx != 2;
}
@Override
public boolean afterPrimaryFinish(IgniteEx primary, IgniteUuid nearXidVer, GridFutureAdapter<?> proceedFut) {
log.info("TX: primary finished: [node=" + primary.name() + ", txId=" + order(nearXidVer) + ']');
if (cntr.getAndIncrement() == expCntr) {
log.info("TX: Stopping primary [name=" + primary.name() + ']');
runAsync(() -> {
stopGrid(skipCheckpointOnNodeStop, primary.name());
TestRecordingCommunicationSpi.stopBlockAll();
});
}
return false;
}
};
}, SIZES);
waitForTopology(3);
awaitPartitionMapExchange();
assertPartitionsSame(idleVerify(grid(CLIENT_GRID_NAME), DEFAULT_CACHE_NAME));
assertCountersSame(PARTITION_ID, true, DEFAULT_CACHE_NAME);
startGrid(txTops.get(PARTITION_ID).get1().name());
awaitPartitionMapExchange();
assertPartitionsSame(idleVerify(grid(CLIENT_GRID_NAME), DEFAULT_CACHE_NAME));
assertCountersSame(PARTITION_ID, true, DEFAULT_CACHE_NAME);
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class TxPartitionCounterStateOnePrimaryTwoBackupsTest method doTestPartialCommit_2tx.
/**
* Test scenario:
* <p>
* 1. Start 2 concurrent txs.
* <p>
* 2. Assign counters in specified order.
* <p>
* 3. Prepare tx0 and tx1.
* <p>
* 4. Prevent tx0 from finishing.
* <p>
* 5. Finish tx1 only on backup2.
* <p>
* 6. Stop backup1 and primary. tx0 must commit on backup2.
* <p>
* 7. Validate partitions.
* <p>
* 8. Start backup2.
* <p>
*
* Pass condition: partitions are in sync after backup2 had joined topology.
*
* @param skipCheckpointOnNodeStop {@code True} to skip checkpoint on node restart.
* @param assignOrder Tx counters assign order.
* @throws Exception If failed.
*/
private void doTestPartialCommit_2tx(boolean skipCheckpointOnNodeStop, int[] assignOrder) throws Exception {
final int[] sizes = new int[] { 3, 7 };
// Backup with the index will be restarted.
final int stopBackupIdx = 0;
Map<Integer, T2<Ignite, List<Ignite>>> txTops = runOnPartition(PARTITION_ID, null, BACKUPS, SERVERS_CNT, map -> {
Ignite primary = map.get(PARTITION_ID).get1();
Ignite backup1 = map.get(PARTITION_ID).get2().get(stopBackupIdx);
Ignite backup2 = map.get(PARTITION_ID).get2().get(1);
return new TwoPhaseCommitTxCallbackAdapter(U.map((IgniteEx) primary, assignOrder), U.map((IgniteEx) backup1, new int[] { 1, 0 }, (IgniteEx) backup2, new int[] { 1, 0 }), new HashMap<>(), sizes.length) {
@Override
public boolean beforeBackupFinish(IgniteEx primary, IgniteEx backup, @Nullable IgniteInternalTx primaryTx, IgniteInternalTx backupTx, IgniteUuid nearXidVer, GridFutureAdapter<?> proceedFut) {
int idx = order(nearXidVer);
return idx == 0 || idx == 1 && backup == backup1 || super.beforeBackupFinish(primary, backup, primaryTx, backupTx, nearXidVer, proceedFut);
}
@Override
public boolean afterBackupFinish(IgniteEx primary, IgniteEx backup, IgniteUuid nearXidVer, GridFutureAdapter<?> proceedFut) {
int idx = order(nearXidVer);
log.info("TX: committed on backup [name=" + backup.name() + ", txId=" + idx + ']');
runAsync(() -> {
stopGrid(skipCheckpointOnNodeStop, backup1.name());
stopGrid(skipCheckpointOnNodeStop, primary.name());
TestRecordingCommunicationSpi.stopBlockAll();
});
return true;
}
};
}, sizes);
waitForTopology(2);
awaitPartitionMapExchange();
Ignite backup2 = txTops.get(PARTITION_ID).get2().get(1);
int size = backup2.cache(DEFAULT_CACHE_NAME).size();
// Txs must be committed on last remaining backup.
assertEquals(sizes[0] + sizes[1] + PRELOAD_KEYS_CNT, size);
startGrid(txTops.get(PARTITION_ID).get2().get(stopBackupIdx).name());
awaitPartitionMapExchange();
assertPartitionsSame(idleVerify(grid(CLIENT_GRID_NAME), DEFAULT_CACHE_NAME));
assertCountersSame(PARTITION_ID, true, DEFAULT_CACHE_NAME);
}
use of org.apache.ignite.internal.util.future.GridFutureAdapter in project ignite by apache.
the class TxPartitionCounterStateOnePrimaryTwoBackupsTest method doTestPartialPrepare_2tx.
/**
* Test scenario:
* <p>
* 1. Start 2 transactions.
* <p>
* 2. Assign counters in given order.
* <p>
* 4. Prepare first tx on backups. Prevent preparing on primary and near node triggering rollback by tx recovery.
* <p>
* 5. Fail primary for triggering recovery.
* <p>
* 6. Validate partitions integrity after node left.
*
* @param skipCheckpointOnNodeStop Skip checkpoint on node stop.
* @param sizes Sizes.
* @param assignOrder Assign order.
* @param backup1PrepOrder Backup 1 order.
* @param backup2PrepOrder Backup 2 order.
* @param expCommittedSize Expected committed size.
* @throws Exception If failed.
*/
private void doTestPartialPrepare_2tx(boolean skipCheckpointOnNodeStop, int[] sizes, int[] assignOrder, int[] backup1PrepOrder, int[] backup2PrepOrder, int expCommittedSize) throws Exception {
AtomicInteger cntr = new AtomicInteger();
Map<Integer, T2<Ignite, List<Ignite>>> txTops = runOnPartition(PARTITION_ID, null, BACKUPS, SERVERS_CNT, map -> {
Ignite primary = map.get(PARTITION_ID).get1();
Ignite backup1 = map.get(PARTITION_ID).get2().get(0);
Ignite backup2 = map.get(PARTITION_ID).get2().get(1);
return new TwoPhaseCommitTxCallbackAdapter(U.map((IgniteEx) primary, assignOrder), U.map((IgniteEx) backup1, backup1PrepOrder, (IgniteEx) backup2, backup2PrepOrder), new HashMap<>(), sizes.length) {
@Override
protected boolean onBackupPrepared(IgniteEx backup, IgniteInternalTx tx, int idx) {
super.onBackupPrepared(backup, tx, idx);
if (cntr.getAndIncrement() == 1) {
// Both backups are prepared.
log.info("Stopping primary [name=" + primary.name() + ']');
runAsync(() -> {
stopGrid(skipCheckpointOnNodeStop, primary.name());
TestRecordingCommunicationSpi.stopBlockAll();
});
}
return true;
}
@Override
public boolean afterBackupPrepare(IgniteEx primary, IgniteEx backup, IgniteInternalTx backupTx, IgniteUuid nearXidVer, GridFutureAdapter<?> proceedFut) {
super.afterBackupPrepare(primary, backup, backupTx, nearXidVer, proceedFut);
// Prevent primary and near prepare causing tx rollback on recovery.
return true;
}
};
}, sizes);
waitForTopology(3);
awaitPartitionMapExchange();
assertPartitionsSame(idleVerify(grid(CLIENT_GRID_NAME), DEFAULT_CACHE_NAME));
assertCountersSame(PARTITION_ID, true, DEFAULT_CACHE_NAME);
assertEquals(PRELOAD_KEYS_CNT + expCommittedSize, grid(CLIENT_GRID_NAME).cache(DEFAULT_CACHE_NAME).size());
// Start primary.
startGrid(txTops.get(PARTITION_ID).get1().name());
awaitPartitionMapExchange();
assertPartitionsSame(idleVerify(grid(CLIENT_GRID_NAME), DEFAULT_CACHE_NAME));
assertCountersSame(PARTITION_ID, true, DEFAULT_CACHE_NAME);
}
Aggregations