[HHH-3817] Further refine, test PutFromLoadValidator
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17657 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
d9adc4bc12
commit
2ad3cfb6c0
|
@ -115,11 +115,14 @@ public class PutFromLoadValidator
|
||||||
* may be <code>null</code>
|
* may be <code>null</code>
|
||||||
*/
|
*/
|
||||||
public PutFromLoadValidator(TransactionManager transactionManager) {
|
public PutFromLoadValidator(TransactionManager transactionManager) {
|
||||||
this(transactionManager, NAKED_PUT_INVALIDATION_PERIOD, PENDING_PUT_OVERAGE_PERIOD, PENDING_PUT_RECENT_PERIOD, MAX_PENDING_PUT_DELAY);
|
this(transactionManager, NAKED_PUT_INVALIDATION_PERIOD, PENDING_PUT_OVERAGE_PERIOD,
|
||||||
|
PENDING_PUT_RECENT_PERIOD, MAX_PENDING_PUT_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Constructor variant for use by unit tests; allows control of variouts timeouts by the test. */
|
/** Constructor variant for use by unit tests; allows control of various timeouts by the test. */
|
||||||
protected PutFromLoadValidator(TransactionManager transactionManager, long nakedPutInvalidationPeriod, long pendingPutOveragePeriod, long pendingPutRecentPeriod, long maxPendingPutDelay) {
|
protected PutFromLoadValidator(TransactionManager transactionManager,
|
||||||
|
long nakedPutInvalidationPeriod, long pendingPutOveragePeriod,
|
||||||
|
long pendingPutRecentPeriod, long maxPendingPutDelay) {
|
||||||
this.transactionManager = transactionManager;
|
this.transactionManager = transactionManager;
|
||||||
this.nakedPutInvalidationPeriod = nakedPutInvalidationPeriod;
|
this.nakedPutInvalidationPeriod = nakedPutInvalidationPeriod;
|
||||||
this.pendingPutOveragePeriod = pendingPutOveragePeriod;
|
this.pendingPutOveragePeriod = pendingPutOveragePeriod;
|
||||||
|
@ -127,6 +130,8 @@ public class PutFromLoadValidator
|
||||||
this.maxPendingPutDelay = maxPendingPutDelay;
|
this.maxPendingPutDelay = maxPendingPutDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------- Public
|
||||||
|
|
||||||
public boolean isPutValid(Object key)
|
public boolean isPutValid(Object key)
|
||||||
{
|
{
|
||||||
boolean valid = false;
|
boolean valid = false;
|
||||||
|
@ -264,6 +269,41 @@ public class PutFromLoadValidator
|
||||||
// Guard against memory leaks
|
// Guard against memory leaks
|
||||||
preventOutdatedPendingPuts(pendingPut);
|
preventOutdatedPendingPuts(pendingPut);
|
||||||
}
|
}
|
||||||
|
// -------------------------------------------------------------- Protected
|
||||||
|
|
||||||
|
/** Only for use by unit tests; may be removed at any time */
|
||||||
|
protected int getPendingPutQueueLength() {
|
||||||
|
pendingLock.lock();
|
||||||
|
try {
|
||||||
|
return pendingQueue.size();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
pendingLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Only for use by unit tests; may be removed at any time */
|
||||||
|
protected int getOveragePendingPutQueueLength() {
|
||||||
|
pendingLock.lock();
|
||||||
|
try {
|
||||||
|
return overagePendingQueue.size();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
pendingLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Only for use by unit tests; may be removed at any time */
|
||||||
|
protected int getRemovalQueueLength() {
|
||||||
|
removalsLock.lock();
|
||||||
|
try {
|
||||||
|
return removalsQueue.size();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
removalsLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ---------------------------------------------------------------- Private
|
||||||
|
|
||||||
private Object getOwnerForPut()
|
private Object getOwnerForPut()
|
||||||
{
|
{
|
||||||
|
@ -307,7 +347,7 @@ public class PutFromLoadValidator
|
||||||
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
while (pendingQueue.size() > pos) {
|
while (pendingQueue.size() > pos) {
|
||||||
WeakReference<PendingPut> ref = pendingQueue.get(0);
|
WeakReference<PendingPut> ref = pendingQueue.get(pos);
|
||||||
PendingPut item = ref.get();
|
PendingPut item = ref.get();
|
||||||
if (item == null || item.completed) {
|
if (item == null || item.completed) {
|
||||||
pendingQueue.remove(pos);
|
pendingQueue.remove(pos);
|
||||||
|
@ -343,6 +383,7 @@ public class PutFromLoadValidator
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (item.timestamp < mustCleanTime) {
|
if (item.timestamp < mustCleanTime) {
|
||||||
|
overagePendingQueue.remove(0);
|
||||||
toClean = item;
|
toClean = item;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -357,7 +398,7 @@ public class PutFromLoadValidator
|
||||||
|
|
||||||
// We've found a pendingPut that never happened; clean it up
|
// We've found a pendingPut that never happened; clean it up
|
||||||
if (toClean != null) {
|
if (toClean != null) {
|
||||||
PendingPutMap map = pendingPuts.get(toClean.key);
|
PendingPutMap map = pendingPuts.get(toClean.key);
|
||||||
if (map != null) {
|
if (map != null) {
|
||||||
synchronized (map) {
|
synchronized (map) {
|
||||||
PendingPut cleaned = map.remove(toClean.owner);
|
PendingPut cleaned = map.remove(toClean.owner);
|
||||||
|
|
|
@ -23,13 +23,20 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.test.cache.jbc.access;
|
package org.hibernate.test.cache.jbc.access;
|
||||||
|
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.transaction.Transaction;
|
||||||
import javax.transaction.TransactionManager;
|
import javax.transaction.TransactionManager;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.hibernate.cache.jbc.access.PutFromLoadValidator;
|
import org.hibernate.cache.jbc.access.PutFromLoadValidator;
|
||||||
import org.hibernate.test.cache.jbc.functional.util.DualNodeJtaTransactionManagerImpl;
|
import org.hibernate.test.cache.jbc.functional.util.DualNodeJtaTransactionManagerImpl;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests of {@link PutFromLoadValidator}.
|
* Tests of {@link PutFromLoadValidator}.
|
||||||
*
|
*
|
||||||
|
@ -37,210 +44,385 @@ import junit.framework.TestCase;
|
||||||
*
|
*
|
||||||
* @version $Revision: $
|
* @version $Revision: $
|
||||||
*/
|
*/
|
||||||
public class PutFromLoadValidatorUnitTestCase extends TestCase
|
public class PutFromLoadValidatorUnitTestCase extends TestCase {
|
||||||
{
|
private Object KEY1 = "KEY1";
|
||||||
private Object KEY1= "KEY1";
|
|
||||||
|
|
||||||
private TransactionManager tm;
|
private TransactionManager tm;
|
||||||
|
|
||||||
public PutFromLoadValidatorUnitTestCase(String name) {
|
public PutFromLoadValidatorUnitTestCase(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception
|
protected void setUp() throws Exception {
|
||||||
{
|
super.setUp();
|
||||||
super.setUp();
|
tm = DualNodeJtaTransactionManagerImpl.getInstance("test");
|
||||||
tm = DualNodeJtaTransactionManagerImpl.getInstance("test");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception
|
protected void tearDown() throws Exception {
|
||||||
{
|
try {
|
||||||
try {
|
super.tearDown();
|
||||||
super.tearDown();
|
} finally {
|
||||||
}
|
tm = null;
|
||||||
finally {
|
try {
|
||||||
tm = null;
|
DualNodeJtaTransactionManagerImpl.cleanupTransactions();
|
||||||
try {
|
} finally {
|
||||||
DualNodeJtaTransactionManagerImpl.cleanupTransactions();
|
DualNodeJtaTransactionManagerImpl.cleanupTransactionManagers();
|
||||||
}
|
}
|
||||||
finally {
|
}
|
||||||
DualNodeJtaTransactionManagerImpl.cleanupTransactionManagers();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testNakedPut() throws Exception {
|
public void testNakedPut() throws Exception {
|
||||||
nakedPutTest(false);
|
nakedPutTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNakedPutTransactional() throws Exception {
|
public void testNakedPutTransactional() throws Exception {
|
||||||
nakedPutTest(true);
|
nakedPutTest(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void nakedPutTest(boolean transactional) throws Exception {
|
private void nakedPutTest(boolean transactional) throws Exception {
|
||||||
PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
|
PutFromLoadValidator testee = new PutFromLoadValidator(
|
||||||
if (transactional) {
|
transactional ? tm : null);
|
||||||
tm.begin();
|
if (transactional) {
|
||||||
}
|
tm.begin();
|
||||||
assertTrue(testee.isPutValid(KEY1));
|
}
|
||||||
}
|
assertTrue(testee.isPutValid(KEY1));
|
||||||
|
}
|
||||||
|
|
||||||
public void testRegisteredPut() throws Exception {
|
public void testRegisteredPut() throws Exception {
|
||||||
registeredPutTest(false);
|
registeredPutTest(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegisteredPutTransactional() throws Exception {
|
public void testRegisteredPutTransactional() throws Exception {
|
||||||
registeredPutTest(true);
|
registeredPutTest(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registeredPutTest(boolean transactional) throws Exception {
|
private void registeredPutTest(boolean transactional) throws Exception {
|
||||||
PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
|
PutFromLoadValidator testee = new PutFromLoadValidator(
|
||||||
if (transactional) {
|
transactional ? tm : null);
|
||||||
tm.begin();
|
if (transactional) {
|
||||||
}
|
tm.begin();
|
||||||
testee.registerPendingPut(KEY1);
|
}
|
||||||
assertTrue(testee.isPutValid(KEY1));
|
testee.registerPendingPut(KEY1);
|
||||||
}
|
assertTrue(testee.isPutValid(KEY1));
|
||||||
|
}
|
||||||
|
|
||||||
public void testNakedPutAfterKeyRemoval() throws Exception {
|
public void testNakedPutAfterKeyRemoval() throws Exception {
|
||||||
nakedPutAfterRemovalTest(false, false);
|
nakedPutAfterRemovalTest(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNakedPutAfterKeyRemovalTransactional() throws Exception {
|
public void testNakedPutAfterKeyRemovalTransactional() throws Exception {
|
||||||
nakedPutAfterRemovalTest(true, false);
|
nakedPutAfterRemovalTest(true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNakedPutAfterRegionRemoval() throws Exception {
|
public void testNakedPutAfterRegionRemoval() throws Exception {
|
||||||
nakedPutAfterRemovalTest(false, true);
|
nakedPutAfterRemovalTest(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNakedPutAfterRegionRemovalTransactional() throws Exception {
|
public void testNakedPutAfterRegionRemovalTransactional() throws Exception {
|
||||||
nakedPutAfterRemovalTest(true, true);
|
nakedPutAfterRemovalTest(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void nakedPutAfterRemovalTest(boolean transactional, boolean removeRegion) throws Exception
|
private void nakedPutAfterRemovalTest(boolean transactional,
|
||||||
{
|
boolean removeRegion) throws Exception {
|
||||||
PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
|
PutFromLoadValidator testee = new PutFromLoadValidator(
|
||||||
if (removeRegion) {
|
transactional ? tm : null);
|
||||||
testee.regionRemoved();
|
if (removeRegion) {
|
||||||
}
|
testee.regionRemoved();
|
||||||
else {
|
} else {
|
||||||
testee.keyRemoved(KEY1);
|
testee.keyRemoved(KEY1);
|
||||||
}
|
}
|
||||||
if (transactional) {
|
if (transactional) {
|
||||||
tm.begin();
|
tm.begin();
|
||||||
}
|
}
|
||||||
assertFalse(testee.isPutValid(KEY1));
|
assertFalse(testee.isPutValid(KEY1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegisteredPutAfterKeyRemoval() throws Exception {
|
public void testRegisteredPutAfterKeyRemoval() throws Exception {
|
||||||
registeredPutAfterRemovalTest(false, false);
|
registeredPutAfterRemovalTest(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegisteredPutAfterKeyRemovalTransactional() throws Exception {
|
public void testRegisteredPutAfterKeyRemovalTransactional()
|
||||||
registeredPutAfterRemovalTest(true, false);
|
throws Exception {
|
||||||
}
|
registeredPutAfterRemovalTest(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void testRegisteredPutAfterRegionRemoval() throws Exception {
|
public void testRegisteredPutAfterRegionRemoval() throws Exception {
|
||||||
registeredPutAfterRemovalTest(false, true);
|
registeredPutAfterRemovalTest(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegisteredPutAfterRegionRemovalTransactional() throws Exception {
|
public void testRegisteredPutAfterRegionRemovalTransactional()
|
||||||
registeredPutAfterRemovalTest(true, true);
|
throws Exception {
|
||||||
}
|
registeredPutAfterRemovalTest(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
private void registeredPutAfterRemovalTest(boolean transactional, boolean removeRegion) throws Exception
|
private void registeredPutAfterRemovalTest(boolean transactional,
|
||||||
{
|
boolean removeRegion) throws Exception {
|
||||||
PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
|
PutFromLoadValidator testee = new PutFromLoadValidator(
|
||||||
if (removeRegion) {
|
transactional ? tm : null);
|
||||||
testee.regionRemoved();
|
if (removeRegion) {
|
||||||
}
|
testee.regionRemoved();
|
||||||
else {
|
} else {
|
||||||
testee.keyRemoved(KEY1);
|
testee.keyRemoved(KEY1);
|
||||||
}
|
}
|
||||||
if (transactional) {
|
if (transactional) {
|
||||||
tm.begin();
|
tm.begin();
|
||||||
}
|
}
|
||||||
testee.registerPendingPut(KEY1);
|
testee.registerPendingPut(KEY1);
|
||||||
assertTrue(testee.isPutValid(KEY1));
|
assertTrue(testee.isPutValid(KEY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegisteredPutWithInterveningKeyRemoval() throws Exception {
|
public void testRegisteredPutWithInterveningKeyRemoval() throws Exception {
|
||||||
registeredPutWithInterveningRemovalTest(false, false);
|
registeredPutWithInterveningRemovalTest(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRegisteredPutWithInterveningKeyRemovalTransactional() throws Exception {
|
public void testRegisteredPutWithInterveningKeyRemovalTransactional()
|
||||||
registeredPutWithInterveningRemovalTest(true, false);
|
throws Exception {
|
||||||
}
|
registeredPutWithInterveningRemovalTest(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void testRegisteredPutWithInterveningRegionRemoval() throws Exception {
|
public void testRegisteredPutWithInterveningRegionRemoval()
|
||||||
registeredPutWithInterveningRemovalTest(false, true);
|
throws Exception {
|
||||||
}
|
registeredPutWithInterveningRemovalTest(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
public void testRegisteredPutWithInterveningRegionRemovalTransactional() throws Exception {
|
public void testRegisteredPutWithInterveningRegionRemovalTransactional()
|
||||||
registeredPutWithInterveningRemovalTest(true, true);
|
throws Exception {
|
||||||
}
|
registeredPutWithInterveningRemovalTest(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
private void registeredPutWithInterveningRemovalTest(boolean transactional, boolean removeRegion) throws Exception
|
private void registeredPutWithInterveningRemovalTest(boolean transactional,
|
||||||
{
|
boolean removeRegion) throws Exception {
|
||||||
PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
|
PutFromLoadValidator testee = new PutFromLoadValidator(
|
||||||
if (transactional) {
|
transactional ? tm : null);
|
||||||
tm.begin();
|
if (transactional) {
|
||||||
}
|
tm.begin();
|
||||||
testee.registerPendingPut(KEY1);
|
}
|
||||||
if (removeRegion) {
|
testee.registerPendingPut(KEY1);
|
||||||
testee.regionRemoved();
|
if (removeRegion) {
|
||||||
}
|
testee.regionRemoved();
|
||||||
else {
|
} else {
|
||||||
testee.keyRemoved(KEY1);
|
testee.keyRemoved(KEY1);
|
||||||
}
|
}
|
||||||
assertFalse(testee.isPutValid(KEY1));
|
assertFalse(testee.isPutValid(KEY1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDelayedNakedPutAfterKeyRemoval() throws Exception {
|
public void testDelayedNakedPutAfterKeyRemoval() throws Exception {
|
||||||
delayedNakedPutAfterRemovalTest(false, false);
|
delayedNakedPutAfterRemovalTest(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDelayedNakedPutAfterKeyRemovalTransactional() throws Exception {
|
public void testDelayedNakedPutAfterKeyRemovalTransactional()
|
||||||
delayedNakedPutAfterRemovalTest(true, false);
|
throws Exception {
|
||||||
}
|
delayedNakedPutAfterRemovalTest(true, false);
|
||||||
|
}
|
||||||
|
|
||||||
public void testDelayedNakedPutAfterRegionRemoval() throws Exception {
|
public void testDelayedNakedPutAfterRegionRemoval() throws Exception {
|
||||||
delayedNakedPutAfterRemovalTest(false, true);
|
delayedNakedPutAfterRemovalTest(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDelayedNakedPutAfterRegionRemovalTransactional() throws Exception {
|
public void testDelayedNakedPutAfterRegionRemovalTransactional()
|
||||||
delayedNakedPutAfterRemovalTest(true, true);
|
throws Exception {
|
||||||
}
|
delayedNakedPutAfterRemovalTest(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
private void delayedNakedPutAfterRemovalTest(boolean transactional, boolean removeRegion) throws Exception
|
private void delayedNakedPutAfterRemovalTest(boolean transactional,
|
||||||
{
|
boolean removeRegion) throws Exception {
|
||||||
PutFromLoadValidator testee = new TestValidator(transactional ? tm : null, 100, 1000, 500, 10000);
|
PutFromLoadValidator testee = new TestValidator(transactional ? tm
|
||||||
if (removeRegion) {
|
: null, 100, 1000, 500, 10000);
|
||||||
testee.regionRemoved();
|
if (removeRegion) {
|
||||||
}
|
testee.regionRemoved();
|
||||||
else {
|
} else {
|
||||||
testee.keyRemoved(KEY1);
|
testee.keyRemoved(KEY1);
|
||||||
}
|
}
|
||||||
if (transactional) {
|
if (transactional) {
|
||||||
tm.begin();
|
tm.begin();
|
||||||
}
|
}
|
||||||
Thread.sleep(110);
|
Thread.sleep(110);
|
||||||
assertTrue(testee.isPutValid(KEY1));
|
assertTrue(testee.isPutValid(KEY1));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class TestValidator extends PutFromLoadValidator {
|
public void testMultipleRegistrations() throws Exception {
|
||||||
|
multipleRegistrationtest(false);
|
||||||
|
}
|
||||||
|
|
||||||
protected TestValidator(TransactionManager transactionManager, long nakedPutInvalidationPeriod,
|
public void testMultipleRegistrationsTransactional() throws Exception {
|
||||||
long pendingPutOveragePeriod, long pendingPutRecentPeriod, long maxPendingPutDelay)
|
multipleRegistrationtest(true);
|
||||||
{
|
}
|
||||||
super(transactionManager, nakedPutInvalidationPeriod, pendingPutOveragePeriod, pendingPutRecentPeriod,
|
|
||||||
maxPendingPutDelay);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
private void multipleRegistrationtest(final boolean transactional) throws Exception {
|
||||||
|
final PutFromLoadValidator testee = new PutFromLoadValidator(transactional ? tm : null);
|
||||||
|
|
||||||
|
final CountDownLatch registeredLatch = new CountDownLatch(3);
|
||||||
|
final CountDownLatch finishedLatch = new CountDownLatch(3);
|
||||||
|
final AtomicInteger success = new AtomicInteger();
|
||||||
|
|
||||||
|
Runnable r = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (transactional) {
|
||||||
|
tm.begin();
|
||||||
|
}
|
||||||
|
testee.registerPendingPut(KEY1);
|
||||||
|
registeredLatch.countDown();
|
||||||
|
registeredLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
if (testee.isPutValid(KEY1)) {
|
||||||
|
success.incrementAndGet();
|
||||||
|
}
|
||||||
|
finishedLatch.countDown();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(3);
|
||||||
|
|
||||||
|
// Start with a removal so the "isPutValid" calls will fail if
|
||||||
|
// any of the concurrent activity isn't handled properly
|
||||||
|
|
||||||
|
testee.regionRemoved();
|
||||||
|
|
||||||
|
// Do the registration + isPutValid calls
|
||||||
|
executor.execute(r);
|
||||||
|
executor.execute(r);
|
||||||
|
executor.execute(r);
|
||||||
|
|
||||||
|
finishedLatch.await(5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
assertEquals("All threads succeeded", 3, success.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* White box test for ensuring key removals get cleaned up.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testRemovalCleanup() throws Exception {
|
||||||
|
TestValidator testee = new TestValidator(null, 200, 1000, 500, 10000);
|
||||||
|
testee.keyRemoved("KEY1");
|
||||||
|
testee.keyRemoved("KEY2");
|
||||||
|
Thread.sleep(210);
|
||||||
|
assertEquals(2, testee.getRemovalQueueLength());
|
||||||
|
testee.keyRemoved("KEY1");
|
||||||
|
assertEquals(2, testee.getRemovalQueueLength());
|
||||||
|
testee.keyRemoved("KEY2");
|
||||||
|
assertEquals(2, testee.getRemovalQueueLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Very much a white box test of the logic for ensuring pending
|
||||||
|
* put registrations get cleaned up.
|
||||||
|
*
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public void testPendingPutCleanup() throws Exception {
|
||||||
|
TestValidator testee = new TestValidator(tm, 5000, 600, 300, 900);
|
||||||
|
|
||||||
|
// Start with a regionRemoval so we can confirm at the end that all
|
||||||
|
// registrations have been cleaned out
|
||||||
|
testee.regionRemoved();
|
||||||
|
|
||||||
|
testee.registerPendingPut("1");
|
||||||
|
testee.registerPendingPut("2");
|
||||||
|
testee.registerPendingPut("3");
|
||||||
|
testee.registerPendingPut("4");
|
||||||
|
testee.registerPendingPut("5");
|
||||||
|
testee.registerPendingPut("6");
|
||||||
|
testee.isPutValid("6");
|
||||||
|
testee.isPutValid("2");
|
||||||
|
// ppq = [1,2(c),3,4,5,6(c)]
|
||||||
|
assertEquals(6, testee.getPendingPutQueueLength());
|
||||||
|
assertEquals(0, testee.getOveragePendingPutQueueLength());
|
||||||
|
|
||||||
|
// Sleep past "pendingPutRecentPeriod"
|
||||||
|
Thread.sleep(310);
|
||||||
|
testee.registerPendingPut("7");
|
||||||
|
// White box -- should have cleaned out 2 (completed) but
|
||||||
|
// not gotten to 6 (also removed)
|
||||||
|
// ppq = [1,3,4,5,6(c),7]
|
||||||
|
assertEquals(0, testee.getOveragePendingPutQueueLength());
|
||||||
|
assertEquals(6, testee.getPendingPutQueueLength());
|
||||||
|
|
||||||
|
// Sleep past "pendingPutOveragePeriod"
|
||||||
|
Thread.sleep(310);
|
||||||
|
testee.registerPendingPut("8");
|
||||||
|
// White box -- should have cleaned out 6 (completed) and
|
||||||
|
// moved 1, 3, 4 and 5 to overage queue
|
||||||
|
// oppq = [1,3,4,5] ppq = [7,8]
|
||||||
|
assertEquals(4, testee.getOveragePendingPutQueueLength());
|
||||||
|
assertEquals(2, testee.getPendingPutQueueLength());
|
||||||
|
|
||||||
|
// Sleep past "maxPendingPutDelay"
|
||||||
|
Thread.sleep(310);
|
||||||
|
testee.isPutValid("3");
|
||||||
|
// White box -- should have cleaned out 1 (overage) and
|
||||||
|
// moved 7 to overage queue
|
||||||
|
// oppq = [3(c),4,5,7] ppq=[8]
|
||||||
|
assertEquals(4, testee.getOveragePendingPutQueueLength());
|
||||||
|
assertEquals(1, testee.getPendingPutQueueLength());
|
||||||
|
|
||||||
|
// Sleep past "maxPendingPutDelay"
|
||||||
|
Thread.sleep(310);
|
||||||
|
tm.begin();
|
||||||
|
testee.registerPendingPut("7");
|
||||||
|
Transaction tx = tm.suspend();
|
||||||
|
|
||||||
|
// White box -- should have cleaned out 3 (completed)
|
||||||
|
// and 4 (overage) and moved 8 to overage queue
|
||||||
|
// We now have 5,7,8 in overage and 7tx in pending
|
||||||
|
// oppq = [5,7,8] ppq=[7tx]
|
||||||
|
assertEquals(3, testee.getOveragePendingPutQueueLength());
|
||||||
|
assertEquals(1, testee.getPendingPutQueueLength());
|
||||||
|
|
||||||
|
// Validate that only expected items can do puts, thus indirectly
|
||||||
|
// proving the others have been cleaned out of pendingPuts map
|
||||||
|
assertFalse(testee.isPutValid("1"));
|
||||||
|
// 5 was overage, so should have been cleaned
|
||||||
|
assertEquals(2, testee.getOveragePendingPutQueueLength());
|
||||||
|
assertFalse(testee.isPutValid("2"));
|
||||||
|
// 7 was overage, so should have been cleaned
|
||||||
|
assertEquals(1, testee.getOveragePendingPutQueueLength());
|
||||||
|
assertFalse(testee.isPutValid("3"));
|
||||||
|
assertFalse(testee.isPutValid("4"));
|
||||||
|
assertFalse(testee.isPutValid("5"));
|
||||||
|
assertFalse(testee.isPutValid("6"));
|
||||||
|
assertFalse(testee.isPutValid("7"));
|
||||||
|
assertTrue(testee.isPutValid("8"));
|
||||||
|
tm.resume(tx);
|
||||||
|
assertTrue(testee.isPutValid("7"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestValidator extends PutFromLoadValidator {
|
||||||
|
|
||||||
|
protected TestValidator(TransactionManager transactionManager,
|
||||||
|
long nakedPutInvalidationPeriod, long pendingPutOveragePeriod,
|
||||||
|
long pendingPutRecentPeriod, long maxPendingPutDelay) {
|
||||||
|
super(transactionManager, nakedPutInvalidationPeriod,
|
||||||
|
pendingPutOveragePeriod, pendingPutRecentPeriod,
|
||||||
|
maxPendingPutDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOveragePendingPutQueueLength() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return super.getOveragePendingPutQueueLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPendingPutQueueLength() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return super.getPendingPutQueueLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRemovalQueueLength() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return super.getRemovalQueueLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue