/*
* Copyright (c) 2008-2012, Hazel Bilisim Ltd. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hazelcast.core;
import com.hazelcast.config.Config;
import com.hazelcast.config.SemaphoreConfig;
import com.hazelcast.impl.GroupProperties;
import org.junit.*;
import org.junit.runner.RunWith;
import java.util.Random;
import java.util.concurrent.*;
import static org.junit.Assert.*;
@RunWith(com.hazelcast.util.RandomBlockJUnit4ClassRunner.class)
public class SemaphoreTest {
@BeforeClass
@AfterClass
public static void init() throws Exception {
System.setProperty(GroupProperties.PROP_WAIT_SECONDS_BEFORE_JOIN, "1");
System.setProperty(GroupProperties.PROP_VERSION_CHECK_ENABLED, "false");
Hazelcast.shutdownAll();
}
@Before
public void setUp() throws Exception {
Hazelcast.shutdownAll();
}
@After
public void tearDown() throws Exception {
Hazelcast.shutdownAll();
}
@Test
public void testSemaphoreWithTimeout() {
SemaphoreConfig semaphoreConfig = new SemaphoreConfig("default", 10);
Config config = new Config();
config.addSemaphoreConfig(semaphoreConfig);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
ISemaphore semaphore = instance.getSemaphore("test");
//Test acquire and timeout.
try {
assertEquals(10, semaphore.availablePermits());
semaphore.tryAcquire();
assertEquals(9, semaphore.availablePermits());
assertEquals(false, semaphore.tryAcquire(10, 10, TimeUnit.MILLISECONDS));
assertEquals(9, semaphore.availablePermits());
semaphore.release();
//Test acquire and timeout and check for partial acquisitions.
assertEquals(10, semaphore.availablePermits());
assertEquals(false, semaphore.tryAcquire(20, 10, TimeUnit.MILLISECONDS));
assertEquals(10, semaphore.availablePermits());
} catch (Throwable e) {
fail(e.getMessage());
}
}
@Test
public void testSimpleSemaphore() {
SemaphoreConfig semaphoreConfig = new SemaphoreConfig("default", 1);
Config config = new Config();
config.addSemaphoreConfig(semaphoreConfig);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
ISemaphore semaphore = instance.getSemaphore("test");
assertEquals(1, semaphore.availablePermits());
semaphore.tryAcquire();
assertEquals(0, semaphore.availablePermits());
semaphore.release();
assertEquals(1, semaphore.availablePermits());
semaphore.tryAcquire();
assertEquals(0, semaphore.availablePermits());
semaphore.release();
assertEquals(1, semaphore.availablePermits());
semaphore.tryAcquire();
assertEquals(0, semaphore.availablePermits());
semaphore.release();
assertEquals(1, semaphore.availablePermits());
semaphore.tryAcquire();
assertEquals(0, semaphore.availablePermits());
semaphore.release();
assertEquals(1, semaphore.availablePermits());
}
@Test
public void testSemaphoreReducePermits() {
SemaphoreConfig semaphoreConfig = new SemaphoreConfig("default", 10);
Config config = new Config();
config.addSemaphoreConfig(semaphoreConfig);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
ISemaphore semaphore = instance.getSemaphore("test");
assertEquals(10, semaphore.availablePermits());
semaphore.reducePermits(1);
assertEquals(9, semaphore.availablePermits());
semaphore.tryAcquire(9);
assertEquals(0, semaphore.availablePermits());
semaphore.reducePermits(8);
assertEquals(-8, semaphore.availablePermits());
semaphore.release();
assertEquals(-7, semaphore.availablePermits());
semaphore.release(8);
assertEquals(1, semaphore.availablePermits());
}
@Test
public void testSemaphoreDisconnect() throws InterruptedException {
SemaphoreConfig semaphoreConfig = new SemaphoreConfig("default", 10);
Config config = new Config();
config.setProperty(GroupProperties.PROP_CONNECTION_MONITOR_INTERVAL, "1");
config.setProperty(GroupProperties.PROP_CONNECTION_MONITOR_MAX_FAULTS, "1");
config.addSemaphoreConfig(semaphoreConfig);
HazelcastInstance instance1 = Hazelcast.newHazelcastInstance(config);
HazelcastInstance instance2 = Hazelcast.newHazelcastInstance(config);
ISemaphore semaphore1 = instance1.getSemaphore("test");
ISemaphore semaphore2 = instance2.getSemaphore("test");
assertEquals(10, semaphore1.availablePermits());
semaphore1.tryAcquireAttach(5);
semaphore1.reducePermits(1);
instance1.getLifecycleService().kill();
Thread.sleep(500);
assertEquals(9, semaphore2.availablePermits());
}
@Test
public void testSemaphorePeerDisconnect() throws InterruptedException {
SemaphoreConfig semaphoreConfig = new SemaphoreConfig("default", 10);
Config config = new Config();
config.addSemaphoreConfig(semaphoreConfig);
HazelcastInstance instance1 = Hazelcast.newHazelcastInstance(config);
HazelcastInstance instance2 = Hazelcast.newHazelcastInstance(config);
ISemaphore semaphore1 = instance1.getSemaphore("test");
ISemaphore semaphore2 = instance2.getSemaphore("test");
semaphore2.tryAcquireAttach(5);
int result = semaphore1.availablePermits();
int expectedResult = 5;
assertEquals(expectedResult, result);
final CountDownLatch latch = new CountDownLatch(1);
instance1.getCluster().addMembershipListener(new MembershipListener() {
public void memberAdded(MembershipEvent membershipEvent) {
}
public void memberRemoved(MembershipEvent membershipEvent) {
latch.countDown();
}
});
instance2.getLifecycleService().shutdown();
assertTrue(latch.await(5, TimeUnit.SECONDS));
expectedResult = 10;
result = semaphore1.availablePermits();
assertEquals(expectedResult, result);
}
@Test
public void testAsyncAcquire() throws Exception {
final ISemaphore semaphore = Hazelcast.getSemaphore("test");
assertEquals(0, semaphore.availablePermits());
final Future f1 = semaphore.acquireAsync();
Thread thread = new Thread() {
@Override
public void run() {
for (; ; ) {
try {
f1.get(1, TimeUnit.SECONDS);
break;
} catch (InterruptedException e) {
//expected
semaphore.release();
assertFalse(f1.cancel(false));
break;
} catch (ExecutionException e) {
// not gonna happen
} catch (TimeoutException e) {
// keep trying
}
}
}
};
assertEquals(0, semaphore.availablePermits());
thread.start();
Thread.sleep(3500);
thread.interrupt();
assertEquals(0, semaphore.availablePermits());
}
@Test
public void testSemaphoreIncreasePermits() {
SemaphoreConfig semaphoreConfig = new SemaphoreConfig("default", 1);
Config config = new Config();
config.addSemaphoreConfig(semaphoreConfig);
HazelcastInstance instance = Hazelcast.newHazelcastInstance(config);
ISemaphore semaphore = instance.getSemaphore("test");
assertEquals(1, semaphore.availablePermits());
semaphore.release();
assertEquals(2, semaphore.availablePermits());
}
@Test
public void testSemaphoreTryAcquireTimeout() throws InterruptedException {
ISemaphore semaphore = Hazelcast.getSemaphore("test");
assertEquals(0, semaphore.availablePermits());
try {
semaphore.tryAcquire(5000, TimeUnit.MILLISECONDS);
} catch (InstanceDestroyedException e) {
e.printStackTrace();
}
assertEquals(0, semaphore.availablePermits());
}
@Test
public void testMultiInstanceSemaphore() {
final Random random = new Random();
final int rndTimeMax = 20;
int initialPermits = 2;
HazelcastInstance instance1 = Hazelcast.newHazelcastInstance(null);
HazelcastInstance instance2 = Hazelcast.newHazelcastInstance(null);
HazelcastInstance instance3 = Hazelcast.newHazelcastInstance(null);
final ISemaphore semaphore1 = instance1.getSemaphore("test");
final ISemaphore semaphore2 = instance2.getSemaphore("test");
final ISemaphore semaphore3 = instance3.getSemaphore("test");
semaphore1.release(initialPermits);
assertEquals(initialPermits, semaphore1.availablePermits());
assertEquals(initialPermits, semaphore2.availablePermits());
assertEquals(initialPermits, semaphore3.availablePermits());
Thread thread1 = new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
try {
semaphore1.acquire(2);
Thread.sleep(random.nextInt(rndTimeMax));
semaphore1.release(2);
Thread.sleep(random.nextInt(rndTimeMax));
} catch (InterruptedException e) {
fail(e.getMessage());
} catch (InstanceDestroyedException e) {
fail(e.getMessage());
}
}
}
};
Thread thread2 = new Thread() {
public void run() {
for (int i = 0; i < 200; i++) {
try {
semaphore2.acquire();
Thread.sleep(random.nextInt(rndTimeMax));
semaphore2.release();
Thread.sleep(random.nextInt(rndTimeMax));
} catch (InterruptedException e) {
fail(e.getMessage());
} catch (InstanceDestroyedException e) {
fail(e.getMessage());
}
}
}
};
Thread thread3 = new Thread() {
public void run() {
for (int i = 0; i < 300; i++) {
try {
semaphore3.acquire();
Thread.sleep(random.nextInt(rndTimeMax));
semaphore3.release();
Thread.sleep(random.nextInt(rndTimeMax));
} catch (InterruptedException e) {
fail(e.getMessage());
} catch (InstanceDestroyedException e) {
fail(e.getMessage());
}
}
}
};
thread1.start();
thread2.start();
thread3.start();
try {
thread1.join();
thread2.join();
thread3.join();
} catch (InterruptedException e) {
e.printStackTrace();
fail();
}
assertEquals(initialPermits, semaphore1.availablePermits());
assertEquals(initialPermits, semaphore2.availablePermits());
assertEquals(initialPermits, semaphore3.availablePermits());
}
}