use of org.apache.geode.internal.cache.TXRegionLockRequestImpl in project geode by apache.
the class TXLockServiceDUnitTest method testTXGrantorMigration.
@Test
public void testTXGrantorMigration() throws Exception {
// first make sure some other VM is the grantor
Host.getHost(0).getVM(0).invoke("become lock grantor", () -> {
TXLockService.createDTLS();
TXLockService vm0dtls = TXLockService.getDTLS();
DLockService vm0dlock = ((TXLockServiceImpl) vm0dtls).getInternalDistributedLockService();
vm0dlock.becomeLockGrantor();
});
TXLockService.createDTLS();
checkDLockRecoverGrantorMessageProcessor();
/*
* call TXRecoverGrantorMessageProcessor.process directly to make sure that correct behavior
* occurs
*/
// get txLock and hold it
final List regionLockReqs = new ArrayList();
regionLockReqs.add(new TXRegionLockRequestImpl("/testTXRecoverGrantorMessageProcessor2", new HashSet(Arrays.asList(new String[] { "KEY-1", "KEY-2", "KEY-3", "KEY-4" }))));
TXLockService dtls = TXLockService.getDTLS();
TXLockId txLockId = dtls.txLock(regionLockReqs, Collections.EMPTY_SET);
final DLockService dlock = ((TXLockServiceImpl) dtls).getInternalDistributedLockService();
// GEODE-2024: now cause grantor migration while holding the recoveryReadLock.
// It will lock up in TXRecoverGrantorMessageProcessor until the recoveryReadLock
// is released. Demonstrate that dtls.release() does not block forever and releases the
// recoveryReadLock
// allowing grantor migration to finish
// create an observer that will block recovery messages from being processed
MessageObserver observer = new MessageObserver();
DistributionMessageObserver.setInstance(observer);
try {
System.out.println("starting thread to take over being lock grantor from vm0");
// become the grantor - this will block waiting for a reply to the message blocked by the
// observer
Thread thread = new Thread(() -> {
dlock.becomeLockGrantor();
});
thread.setName("TXLockServiceDUnitTest thread2");
thread.setDaemon(true);
thread.start();
await("waiting for recovery to begin").atMost(10, TimeUnit.SECONDS).until(() -> {
return observer.isPreventingProcessing();
});
// spawn a thread that will unblock message processing
// so that TXLockServiceImpl's "recovering" variable will be set
System.out.println("starting a thread to unblock recovery in 5 seconds");
Thread unblockThread = new Thread(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException("sleep interrupted");
}
System.out.println("releasing block of recovery message processing");
observer.releasePreventionOfProcessing();
});
unblockThread.setName("TXLockServiceDUnitTest unblockThread");
unblockThread.setDaemon(true);
unblockThread.start();
// release txLock - this will block until unblockThread tells the observer
// that it can process its message. Then it should release the recovery read-lock
// allowing the grantor to finish recovery
System.out.println("releasing transaction locks, which should block for a bit");
dtls.release(txLockId);
await("waiting for recovery to finish").atMost(10, TimeUnit.SECONDS).until(() -> {
return !((TXLockServiceImpl) dtls).isRecovering();
});
} finally {
observer.releasePreventionOfProcessing();
DistributionMessageObserver.setInstance(null);
}
}
Aggregations