From 595293417198611f7d62162df613a2d5c4698022 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 29 Mar 2012 10:48:17 -0400 Subject: [PATCH] INT-2502-patch Tighten Mask Validation Polishing and add tests. --- .../integration/util/DefaultLockRegistry.java | 34 +-- .../integration/util/LockRegistry.java | 8 +- .../util/DefaultLockRegistryTests.java | 247 ++++++++++-------- 3 files changed, 153 insertions(+), 136 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/DefaultLockRegistry.java b/spring-integration-core/src/main/java/org/springframework/integration/util/DefaultLockRegistry.java index 3e8b0bbb0a..d6f53c7950 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/DefaultLockRegistry.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/DefaultLockRegistry.java @@ -36,26 +36,26 @@ public final class DefaultLockRegistry implements LockRegistry { private final int mask; /** - * Constructs a DefaultLockRegistry with the default - * mask 0xFF with 256 locks. - */ + * Constructs a DefaultLockRegistry with the default + * mask 0xFF with 256 locks. + */ public DefaultLockRegistry(){ this(0xFF); } /** - * Constructs a DefaultLockRegistry with the supplied - * mask - the mask must have a value (2**n) - 1 where n - * is 1 to 31, creating a hash of 2**n locks. - *

Examples: - *

  • 0x3ff (1023) - 1024 locks
  • - *
  • 0xfff (4095) - 4096 locks
  • - *

    - * @param mask - */ + * Constructs a DefaultLockRegistry with the supplied + * mask - the mask must have a value Math.pow(2, n) - 1 where n + * is 1 to 31, creating a hash of Math.pow(2, n) locks. + *

    Examples: + *

  • 0x3ff (1023) - 1024 locks
  • + *
  • 0xfff (4095) - 4096 locks
  • + *

    + * @param mask + */ public DefaultLockRegistry(int mask){ String bits = Integer.toBinaryString(mask); - Assert.isTrue(bits.lastIndexOf('0') < bits.indexOf('1'), "Mask must be a power of 2 - 1"); + Assert.isTrue(bits.length() < 32 && (mask == 0 || bits.lastIndexOf('0') < bits.indexOf('1') ), "Mask must be a power of 2 - 1"); this.mask = mask; int arraySize = this.mask+1; lockTable = new ReentrantLock[arraySize]; @@ -65,10 +65,10 @@ public final class DefaultLockRegistry implements LockRegistry { } /** - * Obtains a lock by masking the lockKey's hashCode() with - * the mask and using the result as an index to the lock table. - * @param lockKey the object used to derive the lock index. - */ + * Obtains a lock by masking the lockKey's hashCode() with + * the mask and using the result as an index to the lock table. + * @param lockKey the object used to derive the lock index. + */ public Lock obtain(Object lockKey) { Assert.notNull(lockKey, "'lockKey' must not be null"); Integer lockIndex = lockKey.hashCode() & this.mask; diff --git a/spring-integration-core/src/main/java/org/springframework/integration/util/LockRegistry.java b/spring-integration-core/src/main/java/org/springframework/integration/util/LockRegistry.java index 00bc9160fc..7847fe3526 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/util/LockRegistry.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/util/LockRegistry.java @@ -24,10 +24,10 @@ import java.util.concurrent.locks.Lock; public interface LockRegistry { /** - * Obtains the lock associated with the parameter object. - * @param lockRoot The object with which the lock is associated. - * @return The associated lock. - */ + * Obtains the lock associated with the parameter object. + * @param lockKey The object with which the lock is associated. + * @return The associated lock. + */ Lock obtain(Object lockKey); } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/util/DefaultLockRegistryTests.java b/spring-integration-core/src/test/java/org/springframework/integration/util/DefaultLockRegistryTests.java index e4df8f6135..6ae4f82ccb 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/util/DefaultLockRegistryTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/util/DefaultLockRegistryTests.java @@ -24,144 +24,161 @@ import org.junit.Test; /** * @author Gary Russell + * @author Oleg Zhurakousky * @since 2.1.1 * */ public class DefaultLockRegistryTests { - @Test(expected=IllegalArgumentException.class) - public void testBadMask() { - new DefaultLockRegistry(4); - } + @Test(expected=IllegalArgumentException.class) + public void testBadMask() { + new DefaultLockRegistry(4); + } - @Test - public void testSame() { - LockRegistry registry = new DefaultLockRegistry(); - Lock lock1 = registry.obtain(new Object() { + @Test(expected=IllegalArgumentException.class) + public void testBadMaskOutOfRange() {// 32bits + new DefaultLockRegistry(0xffffffff); + } - @Override - public int hashCode() { - return 0; - }}); - Lock lock2 = registry.obtain(new Object() { + @Test + public void testSingleLockCreation() { + LockRegistry registry = new DefaultLockRegistry(0); + Lock a = registry.obtain(23); + Lock b = registry.obtain(new Object()); + Lock c = registry.obtain("hello"); + assertSame(a, b); + assertSame(a, c); + assertSame(b, c); + } - @Override - public int hashCode() { - return 256; - }}); - assertSame(lock1, lock2); - } + @Test + public void testSame() { + LockRegistry registry = new DefaultLockRegistry(); + Lock lock1 = registry.obtain(new Object() { - @Test - public void testDifferent() { - LockRegistry registry = new DefaultLockRegistry(); - Lock lock1 = registry.obtain(new Object() { + @Override + public int hashCode() { + return 0; + }}); + Lock lock2 = registry.obtain(new Object() { - @Override - public int hashCode() { - return 0; - }}); - Lock lock2 = registry.obtain(new Object() { + @Override + public int hashCode() { + return 256; + }}); + assertSame(lock1, lock2); + } - @Override - public int hashCode() { - return 255; - }}); - assertNotSame(lock1, lock2); - } + @Test + public void testDifferent() { + LockRegistry registry = new DefaultLockRegistry(); + Lock lock1 = registry.obtain(new Object() { - @Test - public void testAllDifferentAndSame() { - LockRegistry registry = new DefaultLockRegistry(3); - Lock[] locks = new Lock[4]; - locks[0] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 0; + }}); + Lock lock2 = registry.obtain(new Object() { - @Override - public int hashCode() { - return 0; - }}); - locks[1] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 255; + }}); + assertNotSame(lock1, lock2); + } - @Override - public int hashCode() { - return 1; - }}); - locks[2] = registry.obtain(new Object() { + @Test + public void testAllDifferentAndSame() { + LockRegistry registry = new DefaultLockRegistry(3); + Lock[] locks = new Lock[4]; + locks[0] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 2; - }}); - locks[3] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 0; + }}); + locks[1] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 3; - }}); - for (int i = 0; i < 4; i++) { - for (int j = 1; j < 4; j++) { - if (i != j) { - assertNotSame(locks[i], locks[j]); - } - } - } - Lock[] moreLocks = new Lock[4]; - moreLocks[0] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 1; + }}); + locks[2] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 0; - }}); - moreLocks[1] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 2; + }}); + locks[3] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 1; - }}); - moreLocks[2] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 3; + }}); + for (int i = 0; i < 4; i++) { + for (int j = 1; j < 4; j++) { + if (i != j) { + assertNotSame(locks[i], locks[j]); + } + } + } + Lock[] moreLocks = new Lock[4]; + moreLocks[0] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 2; - }}); - moreLocks[3] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 0; + }}); + moreLocks[1] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 3; - }}); - assertSame(locks[0], moreLocks[0]); - assertSame(locks[1], moreLocks[1]); - assertSame(locks[2], moreLocks[2]); - assertSame(locks[3], moreLocks[3]); - moreLocks[0] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 1; + }}); + moreLocks[2] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 4; - }}); - moreLocks[1] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 2; + }}); + moreLocks[3] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 5; - }}); - moreLocks[2] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 3; + }}); + assertSame(locks[0], moreLocks[0]); + assertSame(locks[1], moreLocks[1]); + assertSame(locks[2], moreLocks[2]); + assertSame(locks[3], moreLocks[3]); + moreLocks[0] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 6; - }}); - moreLocks[3] = registry.obtain(new Object() { + @Override + public int hashCode() { + return 4; + }}); + moreLocks[1] = registry.obtain(new Object() { - @Override - public int hashCode() { - return 7; - }}); - assertSame(locks[0], moreLocks[0]); - assertSame(locks[1], moreLocks[1]); - assertSame(locks[2], moreLocks[2]); - assertSame(locks[3], moreLocks[3]); - } + @Override + public int hashCode() { + return 5; + }}); + moreLocks[2] = registry.obtain(new Object() { + + @Override + public int hashCode() { + return 6; + }}); + moreLocks[3] = registry.obtain(new Object() { + + @Override + public int hashCode() { + return 7; + }}); + assertSame(locks[0], moreLocks[0]); + assertSame(locks[1], moreLocks[1]); + assertSame(locks[2], moreLocks[2]); + assertSame(locks[3], moreLocks[3]); + } } \ No newline at end of file